James McCool commited on
Commit
158eaa8
·
1 Parent(s): 2e3cd9d

Add exposure management feature in app.py and implement exposure_spread function

Browse files

- Introduced a new exposure management section in the app interface, allowing users to set target exposure for specific players.
- Added the exposure_spread function to adjust player exposure in lineups based on user-defined targets, enhancing lineup optimization.
- Updated session state handling to ensure proper data flow and management during exposure adjustments.

Files changed (2) hide show
  1. app.py +12 -0
  2. global_func/exposure_spread.py +44 -0
app.py CHANGED
@@ -25,6 +25,7 @@ from global_func.volatility_preset import volatility_preset
25
  from global_func.reduce_volatility_preset import reduce_volatility_preset
26
  from global_func.analyze_player_combos import analyze_player_combos
27
  from global_func.stratification_function import stratification_function
 
28
 
29
  freq_format = {'Finish_percentile': '{:.2%}', 'Lineup Edge': '{:.2%}', 'Win%': '{:.2%}'}
30
  stacking_sports = ['MLB', 'NHL', 'NFL']
@@ -1147,6 +1148,17 @@ with tab2:
1147
  parsed_frame = stratification_function(st.session_state['working_frame'], lineup_target, excluded_cols, sport_var, sorting_choice)
1148
  st.session_state['working_frame'] = parsed_frame.reset_index(drop=True)
1149
  st.session_state['export_merge'] = st.session_state['working_frame'].copy()
 
 
 
 
 
 
 
 
 
 
 
1150
  with st.container():
1151
  if 'export_base' not in st.session_state:
1152
  st.session_state['export_base'] = pd.DataFrame(columns=st.session_state['working_frame'].columns)
 
25
  from global_func.reduce_volatility_preset import reduce_volatility_preset
26
  from global_func.analyze_player_combos import analyze_player_combos
27
  from global_func.stratification_function import stratification_function
28
+ from global_func.exposure_spread import exposure_spread
29
 
30
  freq_format = {'Finish_percentile': '{:.2%}', 'Lineup Edge': '{:.2%}', 'Win%': '{:.2%}'}
31
  stacking_sports = ['MLB', 'NHL', 'NFL']
 
1148
  parsed_frame = stratification_function(st.session_state['working_frame'], lineup_target, excluded_cols, sport_var, sorting_choice)
1149
  st.session_state['working_frame'] = parsed_frame.reset_index(drop=True)
1150
  st.session_state['export_merge'] = st.session_state['working_frame'].copy()
1151
+ with st.expander('Exposure Management'):
1152
+ with st.form(key='Exposures'):
1153
+ exposure_player = st.selectbox("Player", options=sorted(list(player_names)), default=[])
1154
+ exposure_target = st.number_input("Target Exposure", value=.25, min_value=0.0, max_value=1.0, step=0.01)
1155
+ exposure_stack_bool = st.selectbox("Maintain Stacks?", options=['Yes', 'No'], index=0)
1156
+ submitted = st.form_submit_button("Submit")
1157
+ if submitted:
1158
+ st.session_state['settings_base'] = False
1159
+ parsed_frame = exposure_spread(st.session_state['working_frame'], exposure_player, exposure_target, exposure_stack_bool, st.session_state['projections_df'])
1160
+ st.session_state['working_frame'] = parsed_frame.reset_index(drop=True)
1161
+ st.session_state['export_merge'] = st.session_state['working_frame'].copy()
1162
  with st.container():
1163
  if 'export_base' not in st.session_state:
1164
  st.session_state['export_base'] = pd.DataFrame(columns=st.session_state['working_frame'].columns)
global_func/exposure_spread.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+
3
+ #### Goal is to choose a player and adjust the amount of lineups that have them
4
+ #### 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
5
+ #### Take that list of players and create a list that can be accessed for random insertion into the portfolio
6
+ #### Find the player and the amount of rows that contain them and then find an exposure rate which is the percentage of total rows
7
+ #### 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
8
+
9
+ def exposure_spread(working_frame, exposure_player, exposure_target, exposure_stack_bool, projections_df):
10
+ # Find comparable players in the projections
11
+ comparable_players = projections_df[projections_df['player_names'] == exposure_player]
12
+ comp_salary_high = comparable_players['salary']
13
+ comp_salary_low = comparable_players['salary'] - 500
14
+ comp_projection_high = comparable_players['Projection']
15
+ comp_projection_low = comparable_players['Projection'] - (comparable_players['Projection'] * .9)
16
+
17
+ comparable_players = projections_df[
18
+ (projections_df['salary'] >= comp_salary_low) &
19
+ (projections_df['salary'] <= comp_salary_high) &
20
+ (projections_df['Projection'] >= comp_projection_low) &
21
+ (projections_df['Projection'] <= comp_projection_high)
22
+ ]
23
+
24
+ # Create a list of comparable players
25
+ comparable_player_list = comparable_players['Name'].tolist()
26
+
27
+ # find the exposure rate of the player in the working frame
28
+ player_mask = working_frame[working_frame.columns].apply(
29
+ lambda row: exposure_player in list(row), axis=1
30
+ )
31
+ player_exposure = player_mask.sum() / len(working_frame)
32
+
33
+ # find the number of lineups that need to be removed to reach the target exposure
34
+ lineups_to_remove = (player_exposure - exposure_target) * len(working_frame)
35
+
36
+ # isolate the rows that contain the player
37
+ player_rows = working_frame[player_mask]
38
+
39
+ # for each row, replace with random choice from comparable player list
40
+ for row in player_rows.index:
41
+ working_frame.at[row, 'player_names'] = random.choice(comparable_player_list)
42
+
43
+ return working_frame
44
+