singhn9 commited on
Commit
3706982
·
verified ·
1 Parent(s): cd1029d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +241 -142
app.py CHANGED
@@ -1,4 +1,3 @@
1
- # app.py (fixed)
2
  import gradio as gr
3
  import pandas as pd
4
  import networkx as nx
@@ -6,9 +5,10 @@ import plotly.graph_objects as go
6
  import numpy as np
7
  from collections import defaultdict
8
 
9
- # ---------------------------
10
- # Data (same as before)
11
- # ---------------------------
 
12
  AMCS = [
13
  "SBI MF", "ICICI Pru MF", "HDFC MF", "Nippon India MF", "Kotak MF",
14
  "UTI MF", "Axis MF", "Aditya Birla SL MF", "Mirae MF", "DSP MF"
@@ -47,7 +47,7 @@ SELL_MAP = {
47
  }
48
 
49
  COMPLETE_EXIT = {
50
- "DSP MF": ["Shriram Finance"],
51
  }
52
 
53
  FRESH_BUY = {
@@ -56,17 +56,23 @@ FRESH_BUY = {
56
  "Mirae MF": ["HAL"]
57
  }
58
 
 
59
  def sanitize_map(m):
60
  out = {}
61
  for k, vals in m.items():
62
  out[k] = [v for v in vals if v in COMPANIES]
63
  return out
64
 
 
65
  BUY_MAP = sanitize_map(BUY_MAP)
66
  SELL_MAP = sanitize_map(SELL_MAP)
67
  COMPLETE_EXIT = sanitize_map(COMPLETE_EXIT)
68
  FRESH_BUY = sanitize_map(FRESH_BUY)
69
 
 
 
 
 
70
  company_edges = []
71
  for amc, comps in BUY_MAP.items():
72
  for c in comps:
@@ -81,206 +87,296 @@ for amc, comps in FRESH_BUY.items():
81
  for c in comps:
82
  company_edges.append((amc, c, {"action": "fresh_buy", "weight": 3}))
83
 
 
84
  def infer_amc_transfers(buy_map, sell_map):
85
  transfers = defaultdict(int)
86
  company_to_sellers = defaultdict(list)
87
  company_to_buyers = defaultdict(list)
 
88
  for amc, comps in sell_map.items():
89
  for c in comps:
90
  company_to_sellers[c].append(amc)
 
91
  for amc, comps in buy_map.items():
92
  for c in comps:
93
  company_to_buyers[c].append(amc)
94
- for c in set(list(company_to_sellers.keys()) + list(company_to_buyers.keys())):
95
- sellers = company_to_sellers.get(c, [])
96
- buyers = company_to_buyers.get(c, [])
 
97
  for s in sellers:
98
  for b in buyers:
99
- transfers[(s,b)] += 1
 
100
  edge_list = []
101
- for (s,b), w in transfers.items():
102
- edge_list.append((s,b, {"action": "transfer", "weight": w, "company_count": w}))
103
  return edge_list
104
 
 
105
  transfer_edges = infer_amc_transfers(BUY_MAP, SELL_MAP)
106
 
 
107
  def build_graph(include_transfers=True):
108
  G = nx.DiGraph()
 
109
  for a in AMCS:
110
- G.add_node(a, type="amc", label=a)
 
111
  for c in COMPANIES:
112
- G.add_node(c, type="company", label=c)
113
- for a, c, attrs in company_edges:
114
- if not G.has_node(a) or not G.has_node(c):
115
- continue
116
- if G.has_edge(a,c):
117
- G[a][c]["weight"] += attrs.get("weight",1)
118
- G[a][c]["actions"].append(attrs["action"])
119
- else:
120
- G.add_edge(a, c, weight=attrs.get("weight",1), actions=[attrs["action"]])
121
- if include_transfers:
122
- for s,b,attrs in transfer_edges:
123
- if not G.has_node(s) or not G.has_node(b):
124
- continue
125
- if G.has_edge(s,b):
126
- G[s][b]["weight"] += attrs.get("weight",1)
127
- G[s][b]["actions"].append("transfer")
128
  else:
129
- G.add_edge(s, b, weight=attrs.get("weight",1), actions=["transfer"])
 
 
 
 
 
 
 
 
 
 
130
  return G
131
 
132
- # ---------------------------
133
- # Visualization
134
- # ---------------------------
135
- def graph_to_plotly(G,
136
- node_color_amc="#9EC5FF",
137
- node_color_company="#FFCF9E",
138
- node_shape_amc="circle",
139
- node_shape_company="circle",
140
- edge_color_buy="#2ca02c",
141
- edge_color_sell="#d62728",
142
- edge_color_transfer="#888888",
143
- edge_thickness_base=1.2,
144
- show_labels=True):
 
 
 
 
145
  pos = nx.spring_layout(G, seed=42, k=1.2)
 
146
  node_x, node_y, node_text, node_color, node_size = [], [], [], [], []
 
147
  for n, d in G.nodes(data=True):
148
  x, y = pos[n]
149
- node_x.append(x); node_y.append(y); node_text.append(n)
 
 
 
150
  if d["type"] == "amc":
151
- node_color.append(node_color_amc); node_size.append(40)
 
152
  else:
153
- node_color.append(node_color_company); node_size.append(60)
 
154
 
155
  node_trace = go.Scatter(
156
  x=node_x, y=node_y,
157
- mode='markers+text' if show_labels else 'markers',
158
- marker=dict(color=node_color, size=node_size, line=dict(width=2, color="#222")),
159
- text=node_text if show_labels else None, textposition="top center", hoverinfo='text'
 
 
 
 
 
160
  )
161
 
162
  edge_traces = []
 
163
  for u, v, attrs in G.edges(data=True):
164
- actions = attrs.get("actions",[])
165
- weight = attrs.get("weight",1)
166
- x0, y0 = pos[u]; x1, y1 = pos[v]
167
- if "complete_exit" in actions:
168
- color = edge_color_sell; dash = "solid"; width = max(edge_thickness_base * 3, 3)
169
- elif "fresh_buy" in actions:
170
- color = edge_color_buy; dash = "solid"; width = max(edge_thickness_base * 3, 3)
171
- elif "transfer" in actions:
172
- color = edge_color_transfer; dash = "dash"; width = max(edge_thickness_base * (1 + np.log1p(weight)), 1.5)
173
- elif "sell" in actions:
174
- color = edge_color_sell; dash = "dot"; width = max(edge_thickness_base * (1 + np.log1p(weight)), 1)
 
 
 
 
 
 
 
 
 
 
 
175
  else:
176
- color = edge_color_buy; dash = "solid"; width = max(edge_thickness_base * (1 + np.log1p(weight)), 1)
177
- trace = go.Scatter(x=[x0, x1, None], y=[y0, y1, None],
178
- line=dict(width=width, color=color, dash=dash),
179
- hoverinfo='none', mode='lines')
180
- edge_traces.append(trace)
181
-
182
- fig = go.Figure(data=edge_traces + [node_trace],
183
- layout=go.Layout(showlegend=False, margin=dict(b=20,l=5,r=5,t=40),
184
- xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
185
- yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
186
- height=900, width=1400))
 
 
 
 
 
 
 
 
 
 
 
 
187
  return fig
188
 
189
- # ---------------------------
190
- # Analysis helpers
191
- # ---------------------------
 
 
192
  def company_trade_summary(company_name):
193
- buyers = [amc for amc, comps in BUY_MAP.items() if company_name in comps]
194
- sellers = [amc for amc, comps in SELL_MAP.items() if company_name in comps]
195
- fresh = [amc for amc, comps in FRESH_BUY.items() if company_name in comps]
196
- exits = [amc for amc, comps in COMPLETE_EXIT.items() if company_name in comps]
 
197
  df = pd.DataFrame({
198
- "Role": ["Buyer"]*len(buyers) + ["Seller"]*len(sellers) + ["Fresh buy"]*len(fresh) + ["Complete exit"]*len(exits),
 
199
  "AMC": buyers + sellers + fresh + exits
200
  })
 
201
  if df.empty:
202
- return None, pd.DataFrame([], columns=["Role","AMC"])
 
203
  counts = df.groupby("Role").size().reset_index(name="Count")
204
- fig = go.Figure(go.Bar(x=counts["Role"], y=counts["Count"], marker_color=["green","red","orange","black"][:len(counts)]))
205
- fig.update_layout(title_text=f"Trade summary for {company_name}", height=300, width=600)
 
 
 
 
 
 
 
 
206
  return fig, df
207
 
 
208
  def amc_transfer_summary(amc_name):
209
  sold = SELL_MAP.get(amc_name, [])
210
  transfers = []
 
211
  for s in sold:
212
- buyers = [amc for amc, comps in BUY_MAP.items() if s in comps]
213
  for b in buyers:
214
  transfers.append({"security": s, "buyer_amc": b})
 
215
  df = pd.DataFrame(transfers)
 
216
  if df.empty:
217
- return None, pd.DataFrame([], columns=["security","buyer_amc"])
218
- counts = df['buyer_amc'].value_counts().reset_index()
219
- counts.columns = ['Buyer AMC', 'Count']
220
- fig = go.Figure(go.Bar(x=counts['Buyer AMC'], y=counts['Count'], marker_color='lightslategray'))
221
- fig.update_layout(title_text=f"Inferred transfers from {amc_name}", height=300, width=600)
 
 
 
 
 
 
 
 
 
222
  return fig, df
223
 
224
- # Build an initial figure (no transfers by default)
225
- initial_G = build_graph(include_transfers=True)
226
- initial_fig = graph_to_plotly(initial_G)
 
 
 
 
 
 
 
227
 
228
- # ---------------------------
229
- # Gradio UI (Blocks)
230
- # ---------------------------
231
  with gr.Blocks() as demo:
232
- gr.Markdown("## Mutual Fund Churn explorerinteractive network + transfer analysis")
233
 
234
- # === LARGE FULL-WIDTH NETWORK GRAPH AT TOP ===
235
- network_plot = gr.Plot(value=initial_fig, label="Network graph (drag to zoom)", height=900)
 
 
 
236
 
237
- # === EVERYTHING ELSE BELOW ===
238
  with gr.Accordion("Network Customization", open=True):
239
- with gr.Column():
240
- node_color_company = gr.ColorPicker(value="#FFCF9E", label="Company node color")
241
- node_color_amc = gr.ColorPicker(value="#9EC5FF", label="AMC node color")
242
-
243
- node_shape_company = gr.Dropdown(
244
- choices=["circle","square","diamond"],
245
- value="circle",
246
- label="Company node shape"
247
- )
248
- node_shape_amc = gr.Dropdown(
249
- choices=["circle","square","diamond"],
250
- value="circle",
251
- label="AMC node shape"
252
- )
253
 
254
- edge_color_buy = gr.ColorPicker(value="#2ca02c", label="BUY edge color")
255
- edge_color_sell = gr.ColorPicker(value="#d62728", label="SELL edge color")
256
- edge_color_transfer = gr.ColorPicker(value="#888888", label="Transfer edge color")
 
257
 
258
- edge_thickness = gr.Slider(
259
- minimum=0.5, maximum=6.0, value=1.4, step=0.1,
260
- label="Edge thickness base"
261
- )
262
 
263
- include_transfers = gr.Checkbox(
264
- value=True,
265
- label="Infer AMC → AMC transfers (show loops)"
266
- )
267
 
268
- update_button = gr.Button("Update network graph")
269
 
270
- gr.Markdown("### Inspect a Company (who bought / who sold)")
271
  select_company = gr.Dropdown(choices=COMPANIES, label="Select company")
272
  company_out_plot = gr.Plot(label="Company trade summary")
273
- company_out_table = gr.DataFrame(label="Company trade table")
274
 
275
- gr.Markdown("### Inspect an AMC (transfer chains)")
276
  select_amc = gr.Dropdown(choices=AMCS, label="Select AMC")
277
- amc_out_plot = gr.Plot(label="AMC inferred transfers")
278
  amc_out_table = gr.DataFrame(label="AMC transfer table")
279
 
280
- # --- Callbacks remain identical ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  update_button.click(
282
- fn=update_network,
283
- inputs=[
284
  node_color_company,
285
  node_color_amc,
286
  node_shape_company,
@@ -289,19 +385,22 @@ with gr.Blocks() as demo:
289
  edge_color_sell,
290
  edge_color_transfer,
291
  edge_thickness,
292
- include_transfers
293
  ],
294
- outputs=[network_plot]
295
  )
296
 
297
- select_company.change(
298
- fn=on_company_select,
299
- inputs=[select_company],
300
- outputs=[company_out_plot, company_out_table]
301
- )
302
 
303
- select_amc.change(
304
- fn=on_amc_select,
305
- inputs=[select_amc],
306
- outputs=[amc_out_plot, amc_out_table]
307
- )
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import pandas as pd
3
  import networkx as nx
 
5
  import numpy as np
6
  from collections import defaultdict
7
 
8
+ # ============================================================
9
+ # DATA
10
+ # ============================================================
11
+
12
  AMCS = [
13
  "SBI MF", "ICICI Pru MF", "HDFC MF", "Nippon India MF", "Kotak MF",
14
  "UTI MF", "Axis MF", "Aditya Birla SL MF", "Mirae MF", "DSP MF"
 
47
  }
48
 
49
  COMPLETE_EXIT = {
50
+ "DSP MF": ["Shriram Finance"]
51
  }
52
 
53
  FRESH_BUY = {
 
56
  "Mirae MF": ["HAL"]
57
  }
58
 
59
+
60
  def sanitize_map(m):
61
  out = {}
62
  for k, vals in m.items():
63
  out[k] = [v for v in vals if v in COMPANIES]
64
  return out
65
 
66
+
67
  BUY_MAP = sanitize_map(BUY_MAP)
68
  SELL_MAP = sanitize_map(SELL_MAP)
69
  COMPLETE_EXIT = sanitize_map(COMPLETE_EXIT)
70
  FRESH_BUY = sanitize_map(FRESH_BUY)
71
 
72
+ # ============================================================
73
+ # GRAPH BUILDING
74
+ # ============================================================
75
+
76
  company_edges = []
77
  for amc, comps in BUY_MAP.items():
78
  for c in comps:
 
87
  for c in comps:
88
  company_edges.append((amc, c, {"action": "fresh_buy", "weight": 3}))
89
 
90
+
91
  def infer_amc_transfers(buy_map, sell_map):
92
  transfers = defaultdict(int)
93
  company_to_sellers = defaultdict(list)
94
  company_to_buyers = defaultdict(list)
95
+
96
  for amc, comps in sell_map.items():
97
  for c in comps:
98
  company_to_sellers[c].append(amc)
99
+
100
  for amc, comps in buy_map.items():
101
  for c in comps:
102
  company_to_buyers[c].append(amc)
103
+
104
+ for c in set(company_to_sellers.keys()) | set(company_to_buyers.keys()):
105
+ sellers = company_to_sellers[c]
106
+ buyers = company_to_buyers[c]
107
  for s in sellers:
108
  for b in buyers:
109
+ transfers[(s, b)] += 1
110
+
111
  edge_list = []
112
+ for (s, b), w in transfers.items():
113
+ edge_list.append((s, b, {"action": "transfer", "weight": w}))
114
  return edge_list
115
 
116
+
117
  transfer_edges = infer_amc_transfers(BUY_MAP, SELL_MAP)
118
 
119
+
120
  def build_graph(include_transfers=True):
121
  G = nx.DiGraph()
122
+
123
  for a in AMCS:
124
+ G.add_node(a, type="amc")
125
+
126
  for c in COMPANIES:
127
+ G.add_node(c, type="company")
128
+
129
+ for u, v, attr in company_edges:
130
+ if u in G.nodes and v in G.nodes:
131
+ if G.has_edge(u, v):
132
+ G[u][v]["weight"] += attr["weight"]
133
+ G[u][v]["actions"].append(attr["action"])
 
 
 
 
 
 
 
 
 
134
  else:
135
+ G.add_edge(u, v, weight=attr["weight"], actions=[attr["action"]])
136
+
137
+ if include_transfers:
138
+ for s, b, attr in transfer_edges:
139
+ if s in G.nodes and b in G.nodes:
140
+ if G.has_edge(s, b):
141
+ G[s][b]["weight"] += attr["weight"]
142
+ G[s][b]["actions"].append("transfer")
143
+ else:
144
+ G.add_edge(s, b, weight=attr["weight"], actions=["transfer"])
145
+
146
  return G
147
 
148
+ # ============================================================
149
+ # PLOTLY NETWORK DRAWING
150
+ # ============================================================
151
+
152
+
153
+ def graph_to_plotly(
154
+ G,
155
+ node_color_amc="#9EC5FF",
156
+ node_color_company="#FFCF9E",
157
+ node_shape_amc="circle",
158
+ node_shape_company="circle",
159
+ edge_color_buy="#2ca02c",
160
+ edge_color_sell="#d62728",
161
+ edge_color_transfer="#888888",
162
+ edge_thickness_base=1.4,
163
+ show_labels=True
164
+ ):
165
  pos = nx.spring_layout(G, seed=42, k=1.2)
166
+
167
  node_x, node_y, node_text, node_color, node_size = [], [], [], [], []
168
+
169
  for n, d in G.nodes(data=True):
170
  x, y = pos[n]
171
+ node_x.append(x)
172
+ node_y.append(y)
173
+ node_text.append(n)
174
+
175
  if d["type"] == "amc":
176
+ node_color.append(node_color_amc)
177
+ node_size.append(40)
178
  else:
179
+ node_color.append(node_color_company)
180
+ node_size.append(60)
181
 
182
  node_trace = go.Scatter(
183
  x=node_x, y=node_y,
184
+ mode="markers+text" if show_labels else "markers",
185
+ marker=dict(
186
+ color=node_color,
187
+ size=node_size,
188
+ line=dict(width=2, color="#222")
189
+ ),
190
+ text=node_text if show_labels else None,
191
+ textposition="top center"
192
  )
193
 
194
  edge_traces = []
195
+
196
  for u, v, attrs in G.edges(data=True):
197
+ acts = attrs.get("actions", [])
198
+ weight = attrs.get("weight", 1)
199
+
200
+ x0, y0 = pos[u]
201
+ x1, y1 = pos[v]
202
+
203
+ if "complete_exit" in acts:
204
+ color = edge_color_sell
205
+ dash = "solid"
206
+ width = edge_thickness_base * 3
207
+ elif "fresh_buy" in acts:
208
+ color = edge_color_buy
209
+ dash = "solid"
210
+ width = edge_thickness_base * 3
211
+ elif "transfer" in acts:
212
+ color = edge_color_transfer
213
+ dash = "dash"
214
+ width = edge_thickness_base * (1 + np.log1p(weight))
215
+ elif "sell" in acts:
216
+ color = edge_color_sell
217
+ dash = "dot"
218
+ width = edge_thickness_base * (1 + np.log1p(weight))
219
  else:
220
+ color = edge_color_buy
221
+ dash = "solid"
222
+ width = edge_thickness_base * (1 + np.log1p(weight))
223
+
224
+ edge_traces.append(
225
+ go.Scatter(
226
+ x=[x0, x1, None],
227
+ y=[y0, y1, None],
228
+ mode="lines",
229
+ line=dict(color=color, width=width, dash=dash),
230
+ hoverinfo="none"
231
+ )
232
+ )
233
+
234
+ fig = go.Figure(data=edge_traces + [node_trace])
235
+ fig.update_layout(
236
+ showlegend=False,
237
+ height=900,
238
+ width=1400,
239
+ margin=dict(l=5, r=5, t=40, b=20),
240
+ xaxis=dict(visible=False),
241
+ yaxis=dict(visible=False)
242
+ )
243
  return fig
244
 
245
+ # ============================================================
246
+ # COMPANY & AMC INSPECTION
247
+ # ============================================================
248
+
249
+
250
  def company_trade_summary(company_name):
251
+ buyers = [a for a, comps in BUY_MAP.items() if company_name in comps]
252
+ sellers = [a for a, comps in SELL_MAP.items() if company_name in comps]
253
+ fresh = [a for a, comps in FRESH_BUY.items() if company_name in comps]
254
+ exits = [a for a, comps in COMPLETE_EXIT.items() if company_name in comps]
255
+
256
  df = pd.DataFrame({
257
+ "Role": ["Buyer"] * len(buyers) + ["Seller"] * len(sellers)
258
+ + ["Fresh buy"] * len(fresh) + ["Complete exit"] * len(exits),
259
  "AMC": buyers + sellers + fresh + exits
260
  })
261
+
262
  if df.empty:
263
+ return None, pd.DataFrame([], columns=["Role", "AMC"])
264
+
265
  counts = df.groupby("Role").size().reset_index(name="Count")
266
+
267
+ fig = go.Figure(go.Bar(
268
+ x=counts["Role"],
269
+ y=counts["Count"],
270
+ marker_color=["green", "red", "orange", "black"][:len(counts)]
271
+ ))
272
+ fig.update_layout(
273
+ title_text=f"Trade summary for {company_name}",
274
+ height=300
275
+ )
276
  return fig, df
277
 
278
+
279
  def amc_transfer_summary(amc_name):
280
  sold = SELL_MAP.get(amc_name, [])
281
  transfers = []
282
+
283
  for s in sold:
284
+ buyers = [a for a, comps in BUY_MAP.items() if s in comps]
285
  for b in buyers:
286
  transfers.append({"security": s, "buyer_amc": b})
287
+
288
  df = pd.DataFrame(transfers)
289
+
290
  if df.empty:
291
+ return None, pd.DataFrame([], columns=["security", "buyer_amc"])
292
+
293
+ counts = df["buyer_amc"].value_counts().reset_index()
294
+ counts.columns = ["Buyer AMC", "Count"]
295
+
296
+ fig = go.Figure(go.Bar(
297
+ x=counts["Buyer AMC"],
298
+ y=counts["Count"],
299
+ marker_color="lightslategray"
300
+ ))
301
+ fig.update_layout(
302
+ title_text=f"Inferred transfers from {amc_name}",
303
+ height=300
304
+ )
305
  return fig, df
306
 
307
+ # ============================================================
308
+ # INITIAL GRAPH
309
+ # ============================================================
310
+
311
+ initial_graph = build_graph(include_transfers=True)
312
+ initial_fig = graph_to_plotly(initial_graph)
313
+
314
+ # ============================================================
315
+ # GRADIO UI — CLEAN, FULL-WIDTH LAYOUT
316
+ # ============================================================
317
 
 
 
 
318
  with gr.Blocks() as demo:
319
+ gr.Markdown("## Mutual Fund Churn ExplorerFull Network & Transfer Analysis")
320
 
321
+ # === FULL-WIDTH NETWORK GRAPH AT THE TOP ===
322
+ network_plot = gr.Plot(
323
+ value=initial_fig,
324
+ label="Network graph (drag to zoom)"
325
+ )
326
 
327
+ # === SETTINGS BELOW THE GRAPH ===
328
  with gr.Accordion("Network Customization", open=True):
329
+ node_color_company = gr.ColorPicker("#FFCF9E", label="Company node color")
330
+ node_color_amc = gr.ColorPicker("#9EC5FF", label="AMC node color")
 
 
 
 
 
 
 
 
 
 
 
 
331
 
332
+ node_shape_company = gr.Dropdown(["circle", "square", "diamond"], value="circle",
333
+ label="Company node shape")
334
+ node_shape_amc = gr.Dropdown(["circle", "square", "diamond"], value="circle",
335
+ label="AMC node shape")
336
 
337
+ edge_color_buy = gr.ColorPicker("#2ca02c", label="BUY edge color")
338
+ edge_color_sell = gr.ColorPicker("#d62728", label="SELL edge color")
339
+ edge_color_transfer = gr.ColorPicker("#888888", label="Transfer edge color")
 
340
 
341
+ edge_thickness = gr.Slider(0.5, 6.0, value=1.4, step=0.1, label="Edge thickness base")
342
+ include_transfers = gr.Checkbox(value=True, label="Show AMC→AMC inferred transfers")
 
 
343
 
344
+ update_button = gr.Button("Update Network Graph")
345
 
346
+ gr.Markdown("### Inspect a Company (buyers / sellers)")
347
  select_company = gr.Dropdown(choices=COMPANIES, label="Select company")
348
  company_out_plot = gr.Plot(label="Company trade summary")
349
+ company_out_table = gr.DataFrame(label="Company table")
350
 
351
+ gr.Markdown("### Inspect an AMC (transfer analysis)")
352
  select_amc = gr.Dropdown(choices=AMCS, label="Select AMC")
353
+ amc_out_plot = gr.Plot(label="AMC transfer summary")
354
  amc_out_table = gr.DataFrame(label="AMC transfer table")
355
 
356
+ # === CALLBACKS ===
357
+
358
+ def update_network(node_color_company_val, node_color_amc_val,
359
+ node_shape_company_val, node_shape_amc_val,
360
+ edge_color_buy_val, edge_color_sell_val, edge_color_transfer_val,
361
+ edge_thickness_val, include_transfers_val):
362
+
363
+ G = build_graph(include_transfers=include_transfers_val)
364
+ fig = graph_to_plotly(
365
+ G,
366
+ node_color_amc=node_color_amc_val,
367
+ node_color_company=node_color_company_val,
368
+ node_shape_amc=node_shape_amc_val,
369
+ node_shape_company=node_shape_company_val,
370
+ edge_color_buy=edge_color_buy_val,
371
+ edge_color_sell=edge_color_sell_val,
372
+ edge_color_transfer=edge_color_transfer_val,
373
+ edge_thickness_base=edge_thickness_val,
374
+ )
375
+ return fig
376
+
377
  update_button.click(
378
+ update_network,
379
+ [
380
  node_color_company,
381
  node_color_amc,
382
  node_shape_company,
 
385
  edge_color_sell,
386
  edge_color_transfer,
387
  edge_thickness,
388
+ include_transfers,
389
  ],
390
+ [network_plot]
391
  )
392
 
393
+ def handle_company(company):
394
+ fig, df = company_trade_summary(company)
395
+ return fig, df
 
 
396
 
397
+ def handle_amc(amc):
398
+ fig, df = amc_transfer_summary(amc)
399
+ return fig, df
400
+
401
+ select_company.change(handle_company, select_company, [company_out_plot, company_out_table])
402
+ select_amc.change(handle_amc, select_amc, [amc_out_plot, amc_out_table])
403
+
404
+
405
+ if __name__ == "__main__":
406
+ demo.launch()