# 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 import plotly.graph_objects as go # --------------------------- # 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 (deduplicated + screenshot items) # --------------------------- COMPANIES = [ "ACC", "Adani Ports and SEZ", "Adani Power", "Aditya Birla Lifestyle Brands", "Affle 3i", "Angel One", "Ashok Leyland", "Avenue Supermarts", "Avanti Feeds", "Axis Bank", "AU Small Finance Bank", "Bajaj Finance", "Bajaj Finserv", "Bank Of Maharashtra", "Berger Paints India", "Bharti Airtel", "Canara Bank", "CESC", "CEAT", "Colgate-Palmolive (India)", "Dalmia Bharat", "Dixon Technologies (India)", "Dr. Reddy's Laboratories", "Eternal", "Fortis Healthcare", "Glenmark Pharmaceuticals", "Godrej Industries", "HCC", "HDFC Asset Management Co", "HDFC Bank", "Hindalco Industries", "Hindustan Aeronautics", "Hindustan Unilever", "HPCL", "Hyundai Motor India", "ICICI Bank", "Infosys", "Indian Bank", "IREDA", "ITC", "Jindal Steel", "Karur Vysya Bank", "Kotak Mahindra Bank", "L&T Finance", "Larsen & Toubro", "Mahindra & Mahindra", "Mankind Pharma", "Maruti Suzuki India", "MCX", "Muthoot Finance", "NMDC", "NTPC", "One97 Communications", "Pearl Global Industries", "Persistent Systems", "Praj Industries", "Power Finance Corporation", "Power Grid Corporation Of India", "Premier Energies", "Sai Silks (Kalamandir)", "Shaily Engineering Plastics", "Shilpa Medicare", "Shriram Finance", "SJS Enterprises", "Solar Industries India", "Steel Authority Of India", "Sumitomo Chemical India", "Sundaram Finance", "Suzlon Energy", "Tata Communications", "Tata Consultancy Services", "Tata Elxsi", "Tata Motors", "Tata Motors Passenger Vehicles", "Tata Steel", "Titan Company", "Trent", "Travel Food Services", "Ujjivan Small Finance Bank", "UNO Minda", "Vedanta", "Welspun Corp", "Yatharth Hospital & Trauma Care", "Zydus Lifesciences" ] # --------------------------- # BUY_MAP (from screenshot) # --------------------------- BUY_MAP = { "SBI MF": [ "Bajaj Finance", "Adani Power", "Infosys" ], "ICICI Pru MF": [ "ICICI Bank", "HDFC Bank", "NTPC" ], "HDFC MF": [ "HDFC Bank", "ICICI Bank", "Power Grid Corporation Of India", "Trent" ], "Nippon India MF": [ "Trent", "HDFC Bank", "Colgate-Palmolive (India)", "ITC" ], "Kotak MF": [ "ITC", "HDFC Bank", "L&T Finance" ], "UTI MF": [ "Dixon Technologies (India)", "Bank Of Maharashtra", "Affle 3i" ], "Axis MF": [ "Kotak Mahindra Bank", "AU Small Finance Bank", "Titan Company" ], "Aditya Birla SL MF": [ "Hindustan Unilever", "Thyrocare Technologies", "Mankind Pharma" ], "Mirae MF": [ "ICICI Bank", "Shriram Finance" ], "DSP MF": [ "Tata Consultancy Services", "Axis Bank" ] } # --------------------------- # SELL_MAP (from screenshot) # --------------------------- SELL_MAP = { "SBI MF": [ "HDFC Bank", "ICICI Bank", "Adani Ports and SEZ" ], "ICICI Pru MF": [ "Bharti Airtel", "Axis Bank", "Larsen & Toubro", "Maruti Suzuki India" ], "HDFC MF": [ "NTPC", "Tata Consultancy Services" ], "Nippon India MF": [ "HDFC Asset Management Co", "One97 Communications", "Hyundai Motor India" ], "Kotak MF": [ "Power Finance Corporation", "Solar Industries India", "HPCL" ], "UTI MF": [ "Dr. Reddy's Laboratories", "Bajaj Finance", "Muthoot Finance", "Avenue Supermarts" ], "Axis MF": [ "Bajaj Finance", "UNO Minda", "Jindal Steel", "Sundaram Finance" ], "Aditya Birla SL MF": [ "Fortis Healthcare", "Mahindra & Mahindra", "Suzlon Energy", "Tata Steel", "Vedanta", "Ashok Leyland" ], "Mirae MF": [ "Berger Paints India", "Godrej Industries" ], "DSP MF": [ "Bajaj Finance", "Tata Motors Passenger Vehicles", "Bajaj Finserv" ] } # --------------------------- # COMPLETE_EXIT (from screenshot) # --------------------------- COMPLETE_EXIT = { "ICICI Pru MF": [ "Tata Elxsi", "Avanti Feeds" ], "HDFC MF": [ "IREDA", "HCC" ], "Nippon India MF": [ "Premier Energies", "Welspun Corp", "Zydus Lifesciences" ], "Kotak MF": [ "Travel Food Services", "Colgate-Palmolive (India)" ], "UTI MF": [ "Bajaj Finserv", "Sai Silks (Kalamandir)" ], "Axis MF": [ "Sumitomo Chemical India", "Adani Ports and SEZ", "CEAT", "ACC" ], "Aditya Birla SL MF": [], "Mirae MF": [ "NMDC" ], "DSP MF": [ "Praj Industries" ] } # --------------------------- # FRESH_BUY (from screenshot) # --------------------------- FRESH_BUY = { "SBI MF": [ "Canara Bank", "MCX" ], "ICICI Pru MF": [ "Pearl Global Industries", "Aditya Birla Lifestyle Brands", "Angel One" ], "HDFC MF": [ "Shriram Finance", "Thyrocare Technologies", "SJS Enterprises", "Shilpa Medicare" ], "Nippon India MF": [ "UNO Minda", "Hindalco Industries" ], "Kotak MF": [ "Pearl Global Industries" ], "UTI MF": [ "Tata Communications", "Ujjivan Small Finance Bank", "CESC" ], "Axis MF": [ "Adani Power", "Steel Authority Of India", "Shaily Engineering Plastics", "Persistent Systems", "Hindustan Aeronautics" ], "Aditya Birla SL MF": [ "Eternal", "Hindustan Aeronautics", "Ujjivan Small Finance Bank" ], "Mirae MF": [], "DSP MF": [ "Eternal", "Hindustan Aeronautics", "Ujjivan Small Finance Bank" ] } def sanitize_map(m): out = {} for k, vals in m.items(): out[k] = [v for v in vals if v in COMPANIES] return out # sanitize_map call will keep only items present in COMPANIES 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 # --------------------------- 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)) fresh_buys = [] for amc, comps in FRESH_BUY.items(): for c in comps: fresh_buys.append((amc, c, 2)) # weight 2 or 3 as you prefer loops = [] for a,c,w1 in buys: for c2,b,w2 in sells: if c == c2: loops.append((a, c, b)) loops = list({(a,c,b) for (a,c,b) in loops}) return buys, sells, transfers, loops,fresh_buys BUYS, SELLS, TRANSFERS, LOOPS,FRESH_BUYS_FLOW = 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 go.Figure(), pd.DataFrame([], columns=["Role", "AMC"]) counts = df.groupby("Role").size().reset_index(name="Count") fig = go.Figure(data=[go.Bar(x=counts["Role"], y=counts["Count"])]) fig.update_layout(title=f"Trades for {company}", margin=dict(l=20,r=20,t=40,b=20)) 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 go.Figure(), pd.DataFrame([], columns=["security", "buyer_amc"]) counts = df["buyer_amc"].value_counts().reset_index() counts.columns = ["Buyer AMC", "Count"] fig = go.Figure(data=[go.Bar(x=counts["Buyer AMC"], y=counts["Count"])]) fig.update_layout(title=f"Inferred transfers from {amc}", margin=dict(l=20,r=20,t=40,b=20)) return fig, df # --------------------------------------------------------------------- # JS_TEMPLATE - single triple-quoted string (complete HTML + JS) # --------------------------------------------------------------------- JS_TEMPLATE = """