Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| from data_fetcher import DataFetcher | |
| from valuation import DCFValuation | |
| from utils import (format_number, format_metrics_table, create_price_chart, | |
| format_financial_statement, create_financial_chart, create_spider_chart, | |
| prepare_financial_table, create_key_metrics_chart, create_growth_chart, | |
| create_margin_chart, create_multi_year_growth_chart, create_ratio_chart) | |
| # Initialize classes | |
| data_fetcher = DataFetcher() | |
| dcf_valuation = DCFValuation() | |
| def analyze_stock(ticker, growth_rate, discount_rate, projection_years, format_type): | |
| # Close any existing matplotlib figures to prevent memory issues | |
| plt.close('all') | |
| try: | |
| # Validate inputs | |
| if not ticker: | |
| return {"error": "Please enter a ticker symbol"}, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None | |
| ticker = ticker.upper().strip() | |
| # Fetch data | |
| metrics = data_fetcher.get_key_metrics(ticker) | |
| price_history = data_fetcher.get_price_history(ticker) | |
| financial_statements = data_fetcher.get_financial_statements(ticker) | |
| # Get currency symbol | |
| currency_symbol = metrics.get('Currency Symbol', '$') | |
| # Format metrics for display | |
| formatted_metrics = format_metrics_table(metrics) | |
| # Calculate DCF valuation | |
| try: | |
| fcf = data_fetcher.get_free_cash_flow(ticker) | |
| shares_outstanding = metrics.get('Shares Outstanding', None) | |
| if fcf is not None and shares_outstanding and shares_outstanding != 'N/A': | |
| company_value = dcf_valuation.calculate_dcf( | |
| fcf=fcf, | |
| growth_rate=growth_rate/100, # Convert percentage to decimal | |
| discount_rate=discount_rate/100, # Convert percentage to decimal | |
| years=int(projection_years) | |
| ) | |
| # Format valuation results | |
| valuation_results = { | |
| "Company Value": format_number(company_value, currency_symbol=currency_symbol, format_type=format_type), | |
| "Current Market Cap": formatted_metrics.get("Market Cap", "N/A"), | |
| "Free Cash Flow": format_number(fcf, currency_symbol=currency_symbol, format_type=format_type), | |
| "Growth Rate": f"{growth_rate:.1f}%", | |
| "Discount Rate": f"{discount_rate:.1f}%", | |
| "Projection Years": int(projection_years) | |
| } | |
| if shares_outstanding: | |
| per_share_value = dcf_valuation.calculate_per_share_value(company_value, shares_outstanding) | |
| current_price = metrics.get('Current Price', None) | |
| valuation_results["Estimated Share Value"] = f"{currency_symbol}{per_share_value:.2f}" | |
| valuation_results["Current Share Price"] = f"{currency_symbol}{current_price:.2f}" if current_price else "N/A" | |
| if current_price: | |
| upside = (per_share_value / current_price - 1) * 100 | |
| valuation_results["Potential Upside"] = f"{upside:.1f}%" | |
| else: | |
| valuation_results = {"error": f"Insufficient data for DCF valuation. FCF: {fcf}, Shares: {shares_outstanding}"} | |
| except Exception as e: | |
| valuation_results = {"error": f"Valuation error: {str(e)}"} | |
| # Create price chart | |
| price_fig = create_price_chart(price_history) | |
| # Create spider chart with enhanced metrics | |
| spider_fig = create_spider_chart(metrics, f"{ticker} Financial Metrics") | |
| # Prepare financial statements for display - Annual | |
| annual_income_table = prepare_financial_table( | |
| financial_statements['income_stmt'], | |
| currency_symbol=currency_symbol, | |
| format_type=format_type | |
| ) | |
| annual_balance_table = prepare_financial_table( | |
| financial_statements['balance_sheet'], | |
| currency_symbol=currency_symbol, | |
| format_type=format_type | |
| ) | |
| annual_cash_flow_table = prepare_financial_table( | |
| financial_statements['cash_flow'], | |
| currency_symbol=currency_symbol, | |
| format_type=format_type | |
| ) | |
| # Prepare financial statements for display - Quarterly | |
| quarterly_income_table = prepare_financial_table( | |
| financial_statements['quarterly_income_stmt'], | |
| currency_symbol=currency_symbol, | |
| format_type=format_type | |
| ) | |
| quarterly_balance_table = prepare_financial_table( | |
| financial_statements['quarterly_balance_sheet'], | |
| currency_symbol=currency_symbol, | |
| format_type=format_type | |
| ) | |
| quarterly_cash_flow_table = prepare_financial_table( | |
| financial_statements['quarterly_cash_flow'], | |
| currency_symbol=currency_symbol, | |
| format_type=format_type | |
| ) | |
| # Create financial charts with error handling | |
| try: | |
| income_fig = create_financial_chart(financial_statements['income_stmt'], | |
| f"{ticker} Income Statement", 'bar') | |
| except Exception as e: | |
| income_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Error creating income statement chart: {str(e)}", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| balance_fig = create_financial_chart(financial_statements['balance_sheet'], | |
| f"{ticker} Balance Sheet", 'bar') | |
| except Exception as e: | |
| balance_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Error creating balance sheet chart: {str(e)}", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| cash_flow_fig = create_financial_chart(financial_statements['cash_flow'], | |
| f"{ticker} Cash Flow", 'bar') | |
| except Exception as e: | |
| cash_flow_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Error creating cash flow chart: {str(e)}", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| # Create quarterly financial charts with error handling | |
| try: | |
| q_income_fig = create_financial_chart(financial_statements['quarterly_income_stmt'], | |
| f"{ticker} Quarterly Income Statement", 'bar') | |
| except Exception as e: | |
| q_income_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Quarterly income data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| q_balance_fig = create_financial_chart(financial_statements['quarterly_balance_sheet'], | |
| f"{ticker} Quarterly Balance Sheet", 'bar') | |
| except Exception as e: | |
| q_balance_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Quarterly balance sheet data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| q_cash_flow_fig = create_financial_chart(financial_statements['quarterly_cash_flow'], | |
| f"{ticker} Quarterly Cash Flow", 'bar') | |
| except Exception as e: | |
| q_cash_flow_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Quarterly cash flow data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| # Create additional analysis charts with error handling | |
| try: | |
| revenue_growth_fig = create_growth_chart( | |
| financial_statements['income_stmt'], | |
| 'Total Revenue', | |
| f"{ticker} Revenue Growth" | |
| ) | |
| except Exception as e: | |
| revenue_growth_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Revenue growth data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| margin_fig = create_margin_chart( | |
| financial_statements['income_stmt'], | |
| f"{ticker} Margin Analysis" | |
| ) | |
| except Exception as e: | |
| margin_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Margin analysis data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| # Create key metrics charts with error handling | |
| try: | |
| key_metrics_income = create_key_metrics_chart( | |
| financial_statements['income_stmt'], | |
| f"{ticker} Key Income Metrics", | |
| ['Total Revenue', 'Gross Profit', 'Operating Income', 'Net Income'], | |
| currency_symbol | |
| ) | |
| except Exception as e: | |
| key_metrics_income = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Income metrics data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| key_metrics_balance = create_key_metrics_chart( | |
| financial_statements['balance_sheet'], | |
| f"{ticker} Key Balance Sheet Metrics", | |
| ['Total Assets', 'Total Liabilities Net Minority Interest', 'Total Equity Gross Minority Interest'], | |
| currency_symbol | |
| ) | |
| except Exception as e: | |
| key_metrics_balance = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Balance sheet metrics data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| key_metrics_cash = create_key_metrics_chart( | |
| financial_statements['cash_flow'], | |
| f"{ticker} Key Cash Flow Metrics", | |
| ['Operating Cash Flow', 'Free Cash Flow', 'Capital Expenditures'], | |
| currency_symbol | |
| ) | |
| except Exception as e: | |
| key_metrics_cash = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Cash flow metrics data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| # Create ratio charts with error handling | |
| try: | |
| profitability_fig = create_ratio_chart( | |
| financial_statements['income_stmt'], | |
| f"{ticker} Profitability Ratios", | |
| 'profitability' | |
| ) | |
| except Exception as e: | |
| profitability_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Profitability ratio data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| try: | |
| efficiency_fig = create_ratio_chart( | |
| financial_statements['balance_sheet'], | |
| f"{ticker} Efficiency Ratios", | |
| 'efficiency' | |
| ) | |
| except Exception as e: | |
| efficiency_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Efficiency ratio data not available", | |
| horizontalalignment='center', verticalalignment='center', fontsize=12) | |
| plt.axis('off') | |
| return (formatted_metrics, valuation_results, price_fig, | |
| annual_income_table, annual_balance_table, annual_cash_flow_table, | |
| quarterly_income_table, quarterly_balance_table, quarterly_cash_flow_table, | |
| income_fig, balance_fig, cash_flow_fig, | |
| q_income_fig, q_balance_fig, q_cash_flow_fig, | |
| spider_fig, revenue_growth_fig, margin_fig, | |
| key_metrics_income, key_metrics_balance, key_metrics_cash, | |
| profitability_fig) | |
| except Exception as e: | |
| error_msg = {"error": f"Error: {str(e)}"} | |
| # Create empty figures for all plots | |
| empty_fig = plt.figure(figsize=(10, 6)) | |
| plt.text(0.5, 0.5, f"Error: {str(e)}", | |
| horizontalalignment='center', verticalalignment='center', fontsize=14) | |
| plt.axis('off') | |
| return (error_msg, {"error": str(e)}, empty_fig, | |
| {"error": "Data unavailable"}, {"error": "Data unavailable"}, {"error": "Data unavailable"}, | |
| {"error": "Data unavailable"}, {"error": "Data unavailable"}, {"error": "Data unavailable"}, | |
| empty_fig, empty_fig, empty_fig, empty_fig, empty_fig, empty_fig, | |
| empty_fig, empty_fig, empty_fig, empty_fig, empty_fig, empty_fig, empty_fig) | |
| # Create Gradio interface | |
| with gr.Blocks(title="Stock DCF Valuation Tool") as app: | |
| gr.Markdown("# Stock DCF Valuation Tool") | |
| gr.Markdown("Enter a stock ticker and DCF assumptions to get a valuation") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| ticker_input = gr.Textbox(label="Stock Ticker (e.g., AAPL, RELIANCE.NS)", placeholder="Enter ticker...") | |
| with gr.Row(): | |
| growth_rate = gr.Slider(minimum=0, maximum=250, value=15, step=1, label="Growth Rate (%)") | |
| discount_rate = gr.Slider(minimum=5, maximum=20, value=10, step=0.1, label="Discount Rate (%)") | |
| projection_years = gr.Slider(minimum=1, maximum=10, value=5, step=1, label="Projection Years") | |
| format_type = gr.Radio( | |
| ["auto", "comma", "millions", "billions"], | |
| label="Number Format", | |
| value="millions" | |
| ) | |
| analyze_button = gr.Button("Analyze Stock", variant="primary") | |
| with gr.Column(scale=2): | |
| with gr.Tabs(): | |
| with gr.TabItem("Key Metrics"): | |
| metrics_output = gr.JSON(label="Key Metrics") | |
| spider_chart = gr.Plot(label="Financial Metrics Radar") | |
| with gr.TabItem("DCF Valuation"): | |
| valuation_output = gr.JSON(label="DCF Valuation Results") | |
| price_chart = gr.Plot(label="Price History") | |
| with gr.TabItem("Annual Financials"): | |
| with gr.Tabs(): | |
| with gr.TabItem("Income Statement"): | |
| income_chart = gr.Plot(label="Income Statement Chart") | |
| annual_income_output = gr.JSON(label="Annual Income Statement") | |
| with gr.TabItem("Balance Sheet"): | |
| balance_chart = gr.Plot(label="Balance Sheet Chart") | |
| annual_balance_output = gr.JSON(label="Annual Balance Sheet") | |
| with gr.TabItem("Cash Flow"): | |
| cash_flow_chart = gr.Plot(label="Cash Flow Chart") | |
| annual_cash_flow_output = gr.JSON(label="Annual Cash Flow") | |
| with gr.TabItem("Quarterly Financials"): | |
| with gr.Tabs(): | |
| with gr.TabItem("Income Statement"): | |
| q_income_chart = gr.Plot(label="Quarterly Income Statement Chart") | |
| quarterly_income_output = gr.JSON(label="Quarterly Income Statement") | |
| with gr.TabItem("Balance Sheet"): | |
| q_balance_chart = gr.Plot(label="Quarterly Balance Sheet Chart") | |
| quarterly_balance_output = gr.JSON(label="Quarterly Balance Sheet") | |
| with gr.TabItem("Cash Flow"): | |
| q_cash_flow_chart = gr.Plot(label="Quarterly Cash Flow Chart") | |
| quarterly_cash_flow_output = gr.JSON(label="Quarterly Cash Flow") | |
| with gr.TabItem("Financial Analysis"): | |
| with gr.Tabs(): | |
| with gr.TabItem("Revenue & Growth"): | |
| revenue_growth_chart = gr.Plot(label="Revenue Growth") | |
| key_metrics_income_chart = gr.Plot(label="Key Income Metrics") | |
| with gr.TabItem("Profitability"): | |
| margin_chart = gr.Plot(label="Margin Analysis") | |
| profitability_chart = gr.Plot(label="Profitability Ratios") | |
| with gr.TabItem("Balance Sheet Analysis"): | |
| key_metrics_balance_chart = gr.Plot(label="Key Balance Sheet Metrics") | |
| efficiency_chart = gr.Plot(label="Efficiency Ratios") | |
| with gr.TabItem("Cash Flow Analysis"): | |
| key_metrics_cash_chart = gr.Plot(label="Key Cash Flow Metrics") | |
| # Define function to clear figures when app is closed | |
| def on_close(): | |
| plt.close('all') | |
| # Register the function to be called when the app is closed | |
| app.load(on_close) | |
| analyze_button.click( | |
| analyze_stock, | |
| inputs=[ticker_input, growth_rate, discount_rate, projection_years, format_type], | |
| outputs=[ | |
| metrics_output, | |
| valuation_output, | |
| price_chart, | |
| annual_income_output, | |
| annual_balance_output, | |
| annual_cash_flow_output, | |
| quarterly_income_output, | |
| quarterly_balance_output, | |
| quarterly_cash_flow_output, | |
| income_chart, | |
| balance_chart, | |
| cash_flow_chart, | |
| q_income_chart, | |
| q_balance_chart, | |
| q_cash_flow_chart, | |
| spider_chart, | |
| revenue_growth_chart, | |
| margin_chart, | |
| key_metrics_income_chart, | |
| key_metrics_balance_chart, | |
| key_metrics_cash_chart, | |
| profitability_chart | |
| ] | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| app.launch() | |