import gradio as gr import yfinance as yf import plotly.graph_objs as go import pandas as pd STYLE_BLOCK = """ """ def fetch_data(symbol, req_type): yfsymbol=symbol+".NS" try: ticker = yf.Ticker(yfsymbol) content_html = "" # Info block as cards + big boxes if req_type.lower() == "info": info = ticker.info if not info: content_html = "

No info available

" else: info_categories = { "Company Overview": [ "longName", "symbol", "exchange", "quoteType", "sector", "industry", "fullTimeEmployees", "website", "address1", "city", "state", "zip", "country", "phone" ], "Valuation Metrics": [ "marketCap", "enterpriseValue", "trailingPE", "forwardPE", "pegRatio", "priceToSalesTrailing12Months", "enterpriseToRevenue", "enterpriseToEbitda" ], "Key Financials": [ "fiftyTwoWeekHigh", "fiftyTwoWeekLow", "fiftyDayAverage", "twoHundredDayAverage", "trailingAnnualDividendRate", "trailingAnnualDividendYield", "dividendRate", "dividendYield", "exDividendDate", "lastSplitFactor", "lastSplitDate", "lastDividendValue", "payoutRatio", "beta", "sharesOutstanding", "impliedSharesOutstanding" ], "Operational Details": [ "auditRisk", "boardRisk", "compensationRisk", "shareHolderRightsRisk", "overallRisk", "governanceEpochDate", "compensationAsOfEpochDate" ], "Trading Information": [ "open", "previousClose", "dayLow", "dayHigh", "volume", "averageVolume", "averageVolume10days", "fiftyTwoWeekChange", "SandP52WeekChange", "currency", "regularMarketDayLow", "regularMarketDayHigh", "regularMarketOpen", "regularMarketPreviousClose", "regularMarketPrice", "regularMarketVolume", "regularMarketChange", "regularMarketChangePercent" ], "Analyst & Target": [ "targetMeanPrice", "numberOfAnalystOpinions", "recommendationKey", "recommendationMean" ] } long_summary = info.pop("longBusinessSummary", None) officers = info.pop("companyOfficers", None) categorized_html = "" for category_name, keys in info_categories.items(): category_key_value_html = "" # Collect key-value pairs for this category for key in keys: if key in info and info[key] is not None and info[key] != []: value = info[key] # Format values as appropriate if isinstance(value, (int, float)) and key not in ['longName', 'symbol', 'exchange', 'quoteType', 'sector', 'industry', 'website', 'address1', 'city', 'state', 'zip', 'country', 'phone', 'longBusinessSummary', 'recommendationKey']: if 'marketCap' in key.lower() or 'value' in key.lower() or 'volume' in key.lower(): value = f"{value:,.0f}" # Format large numbers elif 'percent' in key.lower() or 'ratio' in key.lower() or 'yield' in key.lower() or 'beta' in key.lower() or 'payoutRatio' in key.lower(): value = f"{value:.2%}" # Format percentages elif 'price' in key.lower() or 'dividend' in key.lower() or 'average' in key.lower(): value = f"{value:.2f}" # Format currency/prices category_key_value_html += f"

{key.replace('_', ' ').title()}

{value}

" if category_key_value_html: # Only add category header and card if there is content in it categorized_html += f"

{category_name}

{category_key_value_html}
" extra_sections = "" if long_summary: extra_sections += f"

Business Summary

{long_summary}

" if officers: officer_rows = "".join( f"{o.get('name','')}"f"{o.get('title','')}"f"{o.get('age','')}"f"" for o in officers ) officer_table = f"{officer_rows}
NameTitleAge
" extra_sections += f"

Company Officers

{officer_table}
" content_html = f"{categorized_html}{extra_sections}" # Daily chart elif req_type.lower() == "daily": df = yf.download(yfsymbol, period="1y", interval="1d").round(2) if df.empty: content_html = f"

No daily data for {symbol}

" else: if isinstance(df.columns, pd.MultiIndex): df.columns = df.columns.get_level_values(0) low_price = df["Low"].min() high_price = df["High"].max() price_range = high_price - low_price vol_band_min = low_price - (price_range / 5) vol_band_max = low_price vol_max = df["Volume"].max() vol_scale = (vol_band_max - vol_band_min) / vol_max if vol_max > 0 else 1 fig = go.Figure() fig.add_trace(go.Candlestick( x=df.index, open=df["Open"], high=df["High"], low=df["Low"], close=df["Close"], name="Price" )) fig.add_trace(go.Bar( x=df.index, y=df["Volume"] * vol_scale + vol_band_min, name="Volume", marker_color="lightblue", customdata=df["Volume"], hovertemplate="Volume: %{customdata}" )) fig.update_layout( xaxis_title="Date", yaxis_title="Price", yaxis=dict(range=[vol_band_min, high_price]), xaxis_rangeslider_visible=False, height=600 ) chart_html = fig.to_html(full_html=False) table_html = df.tail(30).to_html(classes="styled-table", border=0) content_html = f"{chart_html}

Recent Daily Data (last 30 rows)

{table_html}" # Intraday chart elif req_type.lower() == "intraday": df = yf.download(yfsymbol, period="1d", interval="5m").round(2) if df.empty: content_html = f"

No intraday data for {symbol}

" else: if isinstance(df.columns, pd.MultiIndex): df.columns = df.columns.get_level_values(0) low_price = df["Low"].min() high_price = df["High"].max() price_range = high_price - low_price vol_band_min = low_price - (price_range / 5) vol_band_max = low_price vol_max = df["Volume"].max() vol_scale = (vol_band_max - vol_band_min) / vol_max if vol_max > 0 else 1 fig = go.Figure() fig.add_trace(go.Candlestick( x=df.index, open=df["Open"], high=df["High"], low=df["Low"], close=df["Close"], name="Price" )) fig.add_trace(go.Bar( x=df.index, y=df["Volume"] * vol_scale + vol_band_min, name="Volume", marker_color="orange", customdata=df["Volume"], hovertemplate="Volume: %{customdata}" )) fig.update_layout( xaxis_title="Time", yaxis_title="Price", yaxis=dict(range=[vol_band_min, high_price]), xaxis_rangeslider_visible=False, height=600 ) chart_html = fig.to_html(full_html=False) table_html = df.tail(50).to_html(classes="styled-table", border=0) content_html = f"{chart_html}

Recent Intraday Data (last 50 rows)

{table_html}" # Financial sections elif req_type.lower() == "qresult": df = ticker.quarterly_financials content_html = f"

Quarterly Results

{df.to_html(classes='styled-table', border=0)}" if not df.empty else "

No quarterly results available

" elif req_type.lower() == "result": df = ticker.financials content_html = f"

Annual Results

{df.to_html(classes='styled-table', border=0)}" if not df.empty else "

No annual results available

" elif req_type.lower() == "balance": df = ticker.balance_sheet content_html = f"

Balance Sheet

{df.to_html(classes='styled-table', border=0)}" if not df.empty else "

No balance sheet available

" elif req_type.lower() == "cashflow": df = ticker.cashflow content_html = f"

Cash Flow

{df.to_html(classes='styled-table', border=0)}" if not df.empty else "

No cashflow available

" elif req_type.lower() == "dividend": s = ticker.dividends content_html = f"

Dividend History

{s.to_frame('Dividend').to_html(classes='styled-table', border=0)}" if not s.empty else "

No dividend history available

" elif req_type.lower() == "split": s = ticker.splits content_html = f"

Split History

{s.to_frame('Split').to_html(classes='styled-table', border=0)}" if not s.empty else "

No split history available

" elif req_type.lower() == "other": df = ticker.earnings content_html = f"

Earnings

{df.to_html(classes='styled-table', border=0)}" if not df.empty else "

No earnings data available

" else: content_html = f"

No handler for {req_type}

" except Exception as e: content_html = f"

Error

{str(e)}

" # Wrap the content_html in a complete HTML document structure full_html_output = f""" Stock Data for {symbol} {STYLE_BLOCK} {content_html} """ return full_html_output iface = gr.Interface( fn=fetch_data, inputs=[ gr.Textbox(label="Stock Symbol", value="PNB"), gr.Dropdown( label="Request Type", choices=[ "info", "intraday", "daily", "qresult", "result", "balance", "cashflow", "dividend", "split", "other" ], value="info" ) ], outputs=gr.HTML(label="Full HTML Output"), title="Stock Data API (Full)", description="Fetch data from NSE and yfinance", api_name="fetch_data" ) if __name__ == "__main__": iface.launch(server_name="0.0.0.0", server_port=7860)