Coverage for src/graphs/portfolio_graph.py: 0%

84 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-03 19:06 +0000

1import plotly.colors as pc 

2import plotly.express as px 

3import plotly.graph_objects as go 

4 

5from src.static.static_values_enum import Edition 

6 

7DEFAULT_HEIGHT = 800 

8 

9 

10def plot_portfolio_total(portfolio_df, combined_users, theme): 

11 portfolio_df.sort_values('date', inplace=True) 

12 if 'total_investment_value' in portfolio_df.columns.tolist() \ 

13 and not portfolio_df['total_investment_value'].dropna().empty: 

14 column_data = portfolio_df[['total_value', 'total_investment_value']].columns 

15 

16 # add last investment value to the last row for visual effect 

17 last_investment_value = portfolio_df['total_investment_value'].dropna().tolist()[-1] 

18 portfolio_df.loc[portfolio_df.index[-1], 'total_investment_value'] = last_investment_value 

19 else: 

20 column_data = portfolio_df[['total_value']].columns 

21 

22 fig = px.line(portfolio_df, 

23 x='date', 

24 y=column_data, 

25 title='Total portfolio values of \'' + ','.join(combined_users) + '\' combined', 

26 markers=True) 

27 fig.update_traces(connectgaps=True) 

28 fig.update_layout( 

29 template=theme, 

30 xaxis=dict( 

31 showgrid=True, 

32 gridwidth=1, 

33 ), 

34 ) 

35 return fig 

36 

37 

38def plot_portfolio_all(df, theme, skip_zero=True): 

39 fig = go.Figure() 

40 

41 temp_df = df.drop('account_name', axis=1) 

42 

43 if skip_zero: 

44 temp_df = temp_df.drop('date', axis=1) 

45 temp_df = temp_df.loc[:, (temp_df.sum(axis=0) != 0.0)] 

46 temp_df['date'] = df[['date']] 

47 

48 temp_df = temp_df.set_index('date') 

49 max_value = temp_df.loc[:, temp_df.columns.str.endswith('_value')].max().max() 

50 max_qty = temp_df.loc[:, ~temp_df.columns.str.endswith('_value')].max().max() 

51 

52 # Get a discrete color palette from Plotly 

53 color_palette = pc.qualitative.Plotly 

54 color_index = 0 # Initialize the index for cycling colors 

55 

56 # Sort columns for legend 

57 temp_df = temp_df.reindex(sorted(temp_df.columns), axis=1) 

58 for column in temp_df.columns.tolist(): 

59 current_color = color_palette[color_index] 

60 

61 mode = 'lines' if temp_df[column].size > 1 else 'markers' 

62 if '_value' in column: 

63 trace = go.Scatter(x=temp_df.index, 

64 y=temp_df[column], 

65 mode=mode, 

66 connectgaps=True, 

67 # legendgroup=legend_group, 

68 # showlegend=False, 

69 line=dict(color=current_color), 

70 name=column) 

71 else: 

72 trace = go.Scatter(x=temp_df.index, 

73 y=temp_df[column], 

74 mode=mode, 

75 connectgaps=True, 

76 # legendgroup=legend_group, 

77 line=dict(color=current_color, dash='dash'), 

78 name=column, 

79 yaxis='y2') 

80 fig.add_trace(trace) 

81 color_index = (color_index + 1) % len(color_palette) # Move to the next color 

82 

83 fig.update_layout( 

84 template=theme, 

85 title_text='All', 

86 legend=dict( 

87 orientation='v', 

88 x=1.1, 

89 xanchor='left', 

90 y=1, 

91 font=dict( 

92 size=10 

93 ), 

94 borderwidth=1, 

95 ), 

96 xaxis=dict( 

97 title='date' 

98 ), 

99 

100 yaxis2=dict( 

101 overlaying='y', 

102 side='right', 

103 position=1.0, # Adjust the position of the secondary y-axis 

104 range=[0, max_qty * 1.05], 

105 title='qty/bcx/count', 

106 ), 

107 yaxis1=dict( 

108 showgrid=False, 

109 range=[0, max_value * 1.05], 

110 title='value $', 

111 ), 

112 height=DEFAULT_HEIGHT, 

113 ) 

114 

115 return fig 

116 

117 

118def get_editions_fig(editions_df, theme): 

119 fig = go.Figure() 

120 # max_value = editions_df.loc[:, editions_df.columns.str.endswith('_market_value')].max().max() 

121 # max_bcx = editions_df.loc[:, editions_df.columns.str.endswith('_bcx')].max().max() 

122 

123 # Get a discrete color palette from Plotly 

124 color_palette = pc.qualitative.Plotly 

125 color_index = 0 # Initialize the index for cycling colors 

126 

127 for edition in Edition.list_names(): 

128 if str(edition) + '_bcx' in editions_df.columns.tolist(): 

129 legend_group = edition 

130 current_color = color_palette[color_index] 

131 

132 mode = 'lines' if editions_df[str(edition) + '_market_value'].size > 1 else 'markers' 

133 market_value_trace = go.Scatter(x=editions_df.index, 

134 y=editions_df[str(edition) + '_market_value'], 

135 mode=mode, 

136 legendgroup=legend_group, 

137 line=dict(color=current_color), # Set line color 

138 name=str(edition)) 

139 fig.add_trace(market_value_trace) 

140 mode = 'lines' if editions_df[str(edition) + '_bcx'].size > 1 else 'markers' 

141 bcx__trace = go.Scatter(x=editions_df.index, 

142 y=editions_df[str(edition) + '_bcx'], 

143 mode=mode, 

144 legendgroup=legend_group, 

145 showlegend=False, 

146 line=dict(color=current_color, dash='dash'), 

147 name=str(edition) + ' bcx', 

148 yaxis='y2') 

149 fig.add_trace(bcx__trace) 

150 color_index = (color_index + 1) % len(color_palette) # Move to the next color 

151 

152 current_color = color_palette[color_index] 

153 temp_df = editions_df.copy() 

154 temp_df['all_value'] = temp_df.loc[:, temp_df.columns.str.endswith('_market_value')].sum(axis=1) 

155 temp_df['all_bcx'] = temp_df.loc[:, temp_df.columns.str.endswith('_bcx')].sum(axis=1) 

156 legend_group = 'combined' 

157 mode = 'lines' if temp_df.all_value.size > 1 else 'markers' 

158 market_value_trace = go.Scatter(x=temp_df.index, 

159 y=temp_df.all_value, 

160 mode=mode, 

161 legendgroup=legend_group, 

162 line=dict(color=current_color), # Set line color 

163 name=legend_group) 

164 fig.add_trace(market_value_trace) 

165 mode = 'lines' if temp_df.all_bcx.size > 1 else 'markers' 

166 bcx__trace = go.Scatter(x=temp_df.index, 

167 y=temp_df.all_bcx, 

168 mode=mode, 

169 legendgroup=legend_group, 

170 showlegend=False, 

171 line=dict(color=current_color, dash='dash'), 

172 name=legend_group + ' bcx', 

173 yaxis='y2') 

174 fig.add_trace(bcx__trace) 

175 

176 fig.update_layout( 

177 template=theme, 

178 title_text='Editions', 

179 hovermode='x unified', 

180 margin=dict(l=10, r=10), 

181 legend=dict( 

182 orientation='h', 

183 yanchor='bottom', 

184 y=1.02, 

185 xanchor='right', 

186 x=1 

187 ), 

188 xaxis=dict( 

189 title='date' 

190 ), 

191 

192 yaxis2=dict( 

193 overlaying='y', 

194 side='right', 

195 position=1.0, # Adjust the position of the secondary y-axis 

196 # range=[0, max_bcx * 1.05], 

197 title='bcx', 

198 ), 

199 yaxis1=dict( 

200 showgrid=False, 

201 # range=[0, max_value * 1.05], 

202 title='value $', 

203 ), 

204 height=DEFAULT_HEIGHT, 

205 

206 ) 

207 

208 return fig 

209 

210 

211def get_sps_fig(sps_df, theme): 

212 fig = go.Figure() 

213 max_value = sps_df.loc[:, sps_df.columns.str.endswith('_value')].max().max() 

214 max_qty = sps_df.loc[:, sps_df.columns.str.endswith('_qty')].max().max() 

215 

216 # Get a discrete color palette from Plotly 

217 color_palette = pc.qualitative.Plotly 

218 color_index = 0 # Initialize the index for cycling colors 

219 

220 for column in sps_df.columns.tolist(): 

221 current_color = color_palette[color_index] 

222 legend_group = 'spsp' if 'spsp' in column else 'sps' 

223 

224 mode = 'lines' if sps_df[column].size > 1 else 'markers' 

225 if '_qty' in column: 

226 trace = go.Scatter(x=sps_df.index, 

227 y=sps_df[column], 

228 mode=mode, 

229 legendgroup=legend_group, 

230 showlegend=False, 

231 line=dict(color=current_color, dash='dash'), 

232 name=legend_group + ' qty ', 

233 yaxis='y2') 

234 else: 

235 trace = go.Scatter(x=sps_df.index, 

236 y=sps_df[column], 

237 mode=mode, 

238 legendgroup=legend_group, 

239 line=dict(color=current_color), # Set line color 

240 name=legend_group) 

241 fig.add_trace(trace) 

242 color_index = (color_index + 1) % len(color_palette) # Move to the next color 

243 

244 fig.update_layout( 

245 template=theme, 

246 title_text='SPS', 

247 hovermode='x unified', 

248 margin=dict(l=10, r=10), 

249 legend=dict( 

250 orientation='h', 

251 yanchor='bottom', 

252 y=1.02, 

253 xanchor='right', 

254 x=1 

255 ), 

256 xaxis=dict( 

257 title='date' 

258 ), 

259 

260 yaxis2=dict( 

261 overlaying='y', 

262 side='right', 

263 position=1.0, # Adjust the position of the secondary y-axis 

264 range=[0, max_qty * 1.05], 

265 title='qty', 

266 ), 

267 yaxis1=dict( 

268 showgrid=False, 

269 range=[0, max_value * 1.05], 

270 title='value $', 

271 ), 

272 height=DEFAULT_HEIGHT, 

273 ) 

274 

275 return fig