# app.py # Static weighted semi-layer arc diagram (L1 labels outside) # JS block injected safely (no Python f-strings inside JS) import gradio as gr import pandas as pd import json import numpy as np from collections import defaultdict # --------------------------- # Data # --------------------------- AMCS = [ "SBI MF", "ICICI Pru MF", "HDFC MF", "Nippon India MF", "Kotak MF", "UTI MF", "Axis MF", "Aditya Birla SL MF", "Mirae MF", "DSP MF" ] COMPANIES = [ "HDFC Bank", "ICICI Bank", "Bajaj Finance", "Bajaj Finserv", "Adani Ports", "Tata Motors", "Shriram Finance", "HAL", "TCS", "AU Small Finance Bank", "Pearl Global", "Hindalco", "Tata Elxsi", "Cummins India", "Vedanta" ] BUY_MAP = { "SBI MF": ["Bajaj Finance", "AU Small Finance Bank"], "ICICI Pru MF": ["HDFC Bank"], "HDFC MF": ["Tata Elxsi", "TCS"], "Nippon India MF": ["Hindalco"], "Kotak MF": ["Bajaj Finance"], "UTI MF": ["Adani Ports", "Shriram Finance"], "Axis MF": ["Tata Motors", "Shriram Finance"], "Aditya Birla SL MF": ["AU Small Finance Bank"], "Mirae MF": ["Bajaj Finance", "HAL"], "DSP MF": ["Tata Motors", "Bajaj Finserv"] } SELL_MAP = { "SBI MF": ["Tata Motors"], "ICICI Pru MF": ["Bajaj Finance", "Adani Ports"], "HDFC MF": ["HDFC Bank"], "Nippon India MF": ["Hindalco"], "Kotak MF": ["AU Small Finance Bank"], "UTI MF": ["Hindalco", "TCS"], "Axis MF": ["TCS"], "Aditya Birla SL MF": ["Adani Ports"], "Mirae MF": ["TCS"], "DSP MF": ["HAL", "Shriram Finance"] } COMPLETE_EXIT = {"DSP MF": ["Shriram Finance"]} FRESH_BUY = {"HDFC MF": ["Tata Elxsi"], "UTI MF": ["Adani Ports"], "Mirae MF": ["HAL"]} def sanitize_map(m): out = {} for k, vals in m.items(): out[k] = [v for v in vals if v in COMPANIES] return out BUY_MAP = sanitize_map(BUY_MAP) SELL_MAP = sanitize_map(SELL_MAP) COMPLETE_EXIT = sanitize_map(COMPLETE_EXIT) FRESH_BUY = sanitize_map(FRESH_BUY) # --------------------------- # Infer AMC->AMC transfers # --------------------------- def infer_amc_transfers(buy_map, sell_map): transfers = defaultdict(int) c2s = defaultdict(list) c2b = defaultdict(list) for amc, comps in sell_map.items(): for c in comps: c2s[c].append(amc) for amc, comps in buy_map.items(): for c in comps: c2b[c].append(amc) for c in set(c2s.keys()) | set(c2b.keys()): for s in c2s[c]: for b in c2b[c]: transfers[(s, b)] += 1 return transfers TRANSFER_COUNTS = infer_amc_transfers(BUY_MAP, SELL_MAP) # --------------------------- # Mixed ordering to reduce crossings # --------------------------- def build_mixed_ordering(amcs, companies): mixed = [] n = max(len(amcs), len(companies)) for i in range(n): if i < len(amcs): mixed.append(amcs[i]) if i < len(companies): mixed.append(companies[i]) return mixed NODES = build_mixed_ordering(AMCS, COMPANIES) NODE_TYPE = {n: ("amc" if n in AMCS else "company") for n in NODES} # --------------------------- # Build flows # --------------------------- def build_flows(): buys = [] for amc, comps in BUY_MAP.items(): for c in comps: w = 3 if (amc in FRESH_BUY and c in FRESH_BUY.get(amc, [])) else 1 buys.append((amc, c, w)) sells = [] for amc, comps in SELL_MAP.items(): for c in comps: w = 3 if (amc in COMPLETE_EXIT and c in COMPLETE_EXIT.get(amc, [])) else 1 sells.append((c, amc, w)) transfers = [] for (s,b), w in TRANSFER_COUNTS.items(): transfers.append((s, b, w)) loops = [] # loops: a -> c -> b for a,c,w1 in buys: for c2,b,w2 in sells: if c == c2: loops.append((a, c, b)) # dedupe loops = list({(a,c,b) for (a,c,b) in loops}) return buys, sells, transfers, loops BUYS, SELLS, TRANSFERS, LOOPS = build_flows() # --------------------------- # Inspector summaries # --------------------------- def company_trade_summary(company): buyers = [a for a, cs in BUY_MAP.items() if company in cs] sellers = [a for a, cs in SELL_MAP.items() if company in cs] fresh = [a for a, cs in FRESH_BUY.items() if company in cs] exits = [a for a, cs in COMPLETE_EXIT.items() if company in cs] df = pd.DataFrame({ "Role": (["Buyer"] * len(buyers)) + (["Seller"] * len(sellers)) + (["Fresh buy"] * len(fresh)) + (["Complete exit"] * len(exits)), "AMC": buyers + sellers + fresh + exits }) if df.empty: return None, pd.DataFrame([], columns=["Role", "AMC"]) counts = df.groupby("Role").size().reset_index(name="Count") fig = { "data": [{"type":"bar", "x": counts["Role"].tolist(), "y": counts["Count"].tolist()}], "layout": {"title": f"Trades for {company}"} } return fig, df def amc_transfer_summary(amc): sold = SELL_MAP.get(amc, []) transfers = [] for s in sold: buyers = [a for a, cs in BUY_MAP.items() if s in cs] for b in buyers: transfers.append({"security": s, "buyer_amc": b}) df = pd.DataFrame(transfers) if df.empty: return None, pd.DataFrame([], columns=["security", "buyer_amc"]) counts = df["buyer_amc"].value_counts().reset_index() counts.columns = ["Buyer AMC", "Count"] fig = { "data": [{"type":"bar", "x": counts["Buyer AMC"].tolist(), "y": counts["Count"].tolist()}], "layout": {"title": f"Inferred transfers from {amc}"} } return fig, df # --------------------------- # HTML template (JS inserted safely via replace) # --------------------------- JS_TEMPLATE = """