| import pandas as pd |
| import openai |
| import gradio as gr |
| import yfinance as yf |
| import json |
| import os |
| import matplotlib.pyplot as plt |
| import io |
| from PIL import Image |
| import plotly.graph_objs as go |
| import re |
| import datetime |
|
|
| openai.api_key = os.getenv('yek_oaipen') |
|
|
|
|
|
|
|
|
| |
| def safe_get(data, key, default="-"): |
| return data.get(key) if data.get(key) is not None else default |
|
|
| |
| def format_number(num): |
| if num is None: |
| return "N/A" |
| try: |
| num = float(num) |
| if num >= 1_000_000_000: |
| return f"{num / 1_000_000_000:.2f}B" |
| elif num >= 1_000_000: |
| return f"{num / 1_000_000:.2f}M" |
| elif num >= 1_000: |
| return f"{num / 1_000:.2f}K" |
| else: |
| return f"{num:.2f}" |
| except: |
| return "N/A" |
|
|
| |
| def get_company_overview(ticker): |
| try: |
| stock = yf.Ticker(ticker) |
| info = stock.info |
| |
| company_officers = info.get("companyOfficers", []) |
| ceo = safe_get(info, "ceo") or (company_officers[0]['name'] if company_officers else "N/A") |
| overview = { |
| "company_name": safe_get(info, "longName"), |
| "ticker": safe_get(info, "symbol"), |
| "exchange": safe_get(info, "exchange"), |
| "industry": safe_get(info, "industry"), |
| "ceo": ceo, |
| "year_founded": safe_get(info, "startDate"), |
| "headquarters": f"{safe_get(info, 'city')}, {safe_get(info, 'state')}" if info.get("city") and info.get("state") else "N/A", |
| "description": safe_get(info, "longBusinessSummary"), |
| "website": safe_get(info, "website") |
| } |
| return overview |
| except Exception as e: |
| print(f"Error fetching company overview for {ticker}: {e}") |
| return {} |
|
|
| |
| def get_financial_metrics(ticker): |
| try: |
| stock = yf.Ticker(ticker) |
| info = stock.info |
| metrics = { |
| "market_cap": format_number(safe_get(info, "marketCap")), |
| "enterprise_value": format_number(safe_get(info, "enterpriseValue")), |
| "shares_outstanding": format_number(safe_get(info, "sharesOutstanding")), |
| "total_revenue": format_number(safe_get(info, "totalRevenue")), |
| "employees": format_number(safe_get(info, "fullTimeEmployees")), |
| "gross_profit_margin": f"{safe_get(info, 'grossMargins')*100:.2f}%" if safe_get(info, 'grossMargins') != "-" else "-", |
| "ebitda_margin": f"{safe_get(info, 'ebitdaMargins')*100:.2f}%" if safe_get(info, 'ebitdaMargins') != "-" else "-", |
| "operating_margin": f"{safe_get(info, 'operatingMargins')*100:.2f}%" if safe_get(info, 'operatingMargins') != "-" else "-", |
| "net_profit_margin": f"{safe_get(info, 'profitMargins')*100:.2f}%" if safe_get(info, 'profitMargins') != "-" else "-", |
| "eps_diluted": format_number(safe_get(info, "trailingEps")), |
| "pe_ratio": format_number(safe_get(info, "trailingPE")), |
| "forward_pe_ratio": format_number(safe_get(info, "forwardPE")), |
| "cash": format_number(safe_get(info, "totalCash")), |
| "net_debt": format_number(safe_get(info, "totalDebt") - safe_get(info, "totalCash")) if safe_get(info, "totalDebt") != "-" and safe_get(info, "totalCash") != "-" else "N/A", |
| "debt_to_equity": f"{safe_get(info, 'debtToEquity'):.2f}" if safe_get(info, "debtToEquity") != "-" else "-", |
| "ebit_to_interest": f"{(safe_get(info, 'ebitda') / safe_get(info, 'interestExpense')):.2f}" if safe_get(info, "ebitda") != "-" and safe_get(info, "interestExpense") != "-" else "N/A", |
| "dividendYield": f"{safe_get(info, 'dividendYield')*100:.2f}%" if safe_get(info, "dividendYield") != "-" else "-", |
| "payoutRatio": f"{safe_get(info, 'payoutRatio')*100:.2f}%" if safe_get(info, "payoutRatio") != "-" else "-", |
| "dividendRate": format_number(safe_get(info, "dividendRate")), |
| "revenue_3yr_cagr": "N/A", |
| "eps_diluted_3yr_cagr": "N/A" |
| } |
| return metrics |
| except Exception as e: |
| print(f"Error fetching financial metrics for {ticker}: {e}") |
| return {} |
|
|
| |
| def get_recent_news(ticker): |
| try: |
| stock = yf.Ticker(ticker) |
| news_items = stock.news[:5] |
| news_list = [] |
| for item in news_items: |
| published_time = pd.to_datetime(item.get("providerPublishTime"), unit='s').strftime('%Y-%m-%d') if item.get("providerPublishTime") else "N/A" |
| news_list.append({ |
| "title": item.get("title"), |
| "publisher": item.get("publisher"), |
| "link": item.get("link"), |
| "published_time": published_time |
| }) |
| return news_list |
| except Exception as e: |
| print(f"Error fetching recent news for {ticker}: {e}") |
| return [] |
|
|
| |
| def get_stock_performance(ticker): |
| try: |
| stock = yf.Ticker(ticker) |
| info = stock.info |
| history = stock.history(period="10y") |
|
|
| if history.empty: |
| return { |
| "current_price": "N/A", |
| "52_week_range": "N/A", |
| "ytd_return": "N/A", |
| "1y_total_return": "N/A", |
| "5y_total_return_cagr": "N/A", |
| "10y_total_return_cagr": "N/A" |
| } |
|
|
| current_price = history['Close'].iloc[-1] |
| fifty_two_week_low = safe_get(info, "fiftyTwoWeekLow") |
| fifty_two_week_high = safe_get(info, "fiftyTwoWeekHigh") |
|
|
| try: |
| ytd_start_price = history['Close'].loc[history.index >= f"{pd.Timestamp.now().year}-01-01"].iloc[0] |
| ytd_return = ((current_price - ytd_start_price) / ytd_start_price) * 100 |
| except IndexError: |
| ytd_return = "N/A" |
|
|
| try: |
| one_year_return = ((current_price - history['Close'].iloc[-252]) / history['Close'].iloc[-252]) * 100 |
| except IndexError: |
| one_year_return = "N/A" |
|
|
| try: |
| five_year_return = ((current_price - history['Close'].iloc[-1260]) / history['Close'].iloc[-1260]) * 100 |
| five_year_cagr = five_year_return / 5 |
| except IndexError: |
| five_year_cagr = "N/A" |
|
|
| try: |
| ten_year_return = ((current_price - history['Close'].iloc[0]) / history['Close'].iloc[0]) * 100 |
| ten_year_cagr = ten_year_return / 10 |
| except IndexError: |
| ten_year_cagr = "N/A" |
|
|
| performance = { |
| "current_price": format_number(current_price), |
| "52_week_range": f"{format_number(fifty_two_week_low)} - {format_number(fifty_two_week_high)}", |
| "ytd_return": f"{ytd_return:.2f}%" if isinstance(ytd_return, float) else "N/A", |
| "1y_total_return": f"{one_year_return:.2f}%" if isinstance(one_year_return, float) else "N/A", |
| "5y_total_return_cagr": f"{five_year_cagr:.2f}%" if isinstance(five_year_cagr, float) else "N/A", |
| "10y_total_return_cagr": f"{ten_year_cagr:.2f}%" if isinstance(ten_year_cagr, float) else "N/A" |
| } |
| return performance |
| except Exception as e: |
| print(f"Error fetching stock performance for {ticker}: {e}") |
| return { |
| "current_price": "N/A", |
| "52_week_range": "N/A", |
| "ytd_return": "N/A", |
| "1y_total_return": "N/A", |
| "5y_total_return_cagr": "N/A", |
| "10y_total_return_cagr": "N/A" |
| } |
|
|
| |
| def create_stock_chart(ticker): |
| try: |
| stock = yf.Ticker(ticker) |
| history = stock.history(period="10y") |
| if history.empty: |
| fig = go.Figure() |
| fig.update_layout( |
| title=f"No historical data available for {ticker}", |
| xaxis_title="Date", |
| yaxis_title="Price (USD)", |
| template="plotly_white" |
| ) |
| return fig |
|
|
| fig = go.Figure() |
| fig.add_trace( |
| go.Scatter( |
| x=history.index, |
| y=history['Close'], |
| mode='lines', |
| name='Close Price', |
| line=dict(color='purple'), |
| fill='tozeroy', |
| fillcolor='rgba(128, 0, 128, 0.2)' |
| ) |
| ) |
| fig.update_layout( |
| title=f"Stock Price History for {ticker}", |
| xaxis_title="Date", |
| yaxis_title="Price (USD)", |
| template="plotly_white", |
| hovermode="x unified", |
| plot_bgcolor='white', |
| paper_bgcolor='white', |
| xaxis=dict( |
| showgrid=True, |
| gridcolor='lightgrey' |
| ), |
| yaxis=dict( |
| showgrid=True, |
| gridcolor='lightgrey' |
| ) |
| ) |
| return fig |
| except Exception as e: |
| print(f"Error creating stock chart for {ticker}: {e}") |
| fig = go.Figure() |
| fig.update_layout( |
| title="Error generating chart", |
| xaxis_title="Date", |
| yaxis_title="Price (USD)", |
| template="plotly_white" |
| ) |
| return fig |
|
|
| |
| def get_full_stock_report(ticker): |
| report = { |
| "overview": get_company_overview(ticker), |
| "financial_metrics": get_financial_metrics(ticker), |
| "recent_news": get_recent_news(ticker), |
| "stock_performance": get_stock_performance(ticker) |
| } |
| return report |
|
|
| |
| def format_stock_report(report): |
| overview = report.get('overview', {}) |
| financials = report.get('financial_metrics', {}) |
| news = report.get('recent_news', []) |
| performance = report.get('stock_performance', {}) |
|
|
| formatted_report = f""" |
| **{overview.get('company_name', 'N/A')} ({overview.get('ticker', 'N/A')}) Overview** |
| - **Company Name:** {overview.get('company_name', 'N/A')} |
| - **Ticker:** {overview.get('ticker', 'N/A')} |
| - **Exchange:** {overview.get('exchange', 'N/A')} |
| - **Industry:** {overview.get('industry', 'N/A')} |
| - **CEO:** {overview.get('ceo', 'N/A')} |
| - **Year Founded:** {overview.get('year_founded', 'N/A')} |
| - **Headquarters:** {overview.get('headquarters', 'N/A')} |
| |
| **Description:** {overview.get('description', 'N/A')} |
| |
| **Financial Metrics & Fundamentals** |
| - **Market Cap:** {financials.get('market_cap', 'N/A')} |
| - **Enterprise Value:** {financials.get('enterprise_value', 'N/A')} |
| - **Shares Outstanding:** {financials.get('shares_outstanding', 'N/A')} |
| - **Total Revenues:** {financials.get('total_revenue', 'N/A')} |
| - **Employees:** {financials.get('employees', 'N/A')} |
| - **Gross Profit Margin:** {financials.get('gross_profit_margin', 'N/A')} |
| - **EBITDA Margin:** {financials.get('ebitda_margin', 'N/A')} |
| - **Operating Margin:** {financials.get('operating_margin', 'N/A')} |
| - **Net Profit Margin:** {financials.get('net_profit_margin', 'N/A')} |
| - **EPS Diluted:** {financials.get('eps_diluted', 'N/A')} |
| - **P/E Ratio:** {financials.get('pe_ratio', 'N/A')} |
| - **Forward P/E Ratio:** {financials.get('forward_pe_ratio', 'N/A')} |
| |
| **Financial Health** |
| - **Cash:** {financials.get('cash', 'N/A')} |
| - **Net Debt:** {financials.get('net_debt', 'N/A')} |
| - **Debt/Equity:** {financials.get('debt_to_equity', 'N/A')} |
| - **EBIT/Interest:** {financials.get('ebit_to_interest', 'N/A')} |
| |
| **Dividends** |
| - **Yield:** {financials.get('dividendYield', 'N/A')} |
| - **Payout Ratio:** {financials.get('payoutRatio', 'N/A')} |
| - **DPS:** {financials.get('dividendRate', 'N/A')} |
| |
| **Recent News** |
| """ |
| for item in news: |
| formatted_report += f"- [{item.get('title', 'N/A')}]({item.get('link', '#')}) ({item.get('publisher', 'N/A')}) - {item.get('published_time', 'N/A')}\n" |
|
|
| formatted_report += f""" |
| **Stock Performance** |
| - **Current Price:** {performance.get('current_price', 'N/A')} |
| - **52-Week Range:** {performance.get('52_week_range', 'N/A')} |
| - **YTD Return:** {performance.get('ytd_return', 'N/A')} |
| - **1-Year Total Return:** {performance.get('1y_total_return', 'N/A')} |
| - **5-Year Total Return CAGR:** {performance.get('5y_total_return_cagr', 'N/A')} |
| - **10-Year Total Return CAGR:** {performance.get('10y_total_return_cagr', 'N/A')} |
| |
| **Summary** |
| *Provide a brief summary of the company's performance and outlook.* |
| """ |
| return formatted_report |
|
|
| |
| def get_company_name_from_conversation(conversation): |
| try: |
| |
| user_message = conversation[-1]['content'] |
| |
| response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=[ |
| {"role": "system", "content": "You are an assistant that extracts stock ticker symbols or company names from user messages."}, |
| {"role": "user", "content": user_message} |
| ], |
| max_tokens=20, |
| temperature=0 |
| ) |
|
|
| |
| extracted_name = response['choices'][0]['message']['content'].strip() |
|
|
| |
| if re.match(r'^[A-Za-z\s]+$', extracted_name): |
| return extracted_name |
| else: |
| return None |
| except Exception as e: |
| print(f"Error extracting company name: {e}") |
| return None |
|
|
| |
| def handle_no_stock_found(company_name=None): |
| if company_name: |
| return f""" |
| It seems like you might be asking about the performance of a company such as "{company_name}". |
| However, I need more specific information to proceed, such as the full name or ticker symbol of the company. |
| Could you please clarify further? |
| """ |
| else: |
| return """ |
| It seems like you're asking about the performance of a company, but I couldn't identify a specific company name. |
| Could you please provide more specific information, such as the full name or ticker symbol? |
| """ |
|
|
| |
| functions = [ |
| { |
| "name": "get_full_stock_report", |
| "description": "Retrieve a full stock report for a given ticker symbol.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "ticker": { |
| "type": "string", |
| "description": "The stock ticker symbol, e.g., 'AAPL' for Apple Inc." |
| } |
| }, |
| "required": ["ticker"] |
| } |
| }, |
| { |
| "name": "get_company_overview", |
| "description": "Get an overview of the company for a given ticker symbol.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "ticker": {"type": "string", "description": "The stock ticker symbol."} |
| }, |
| "required": ["ticker"] |
| } |
| }, |
| { |
| "name": "get_financial_metrics", |
| "description": "Get financial metrics for a given ticker symbol.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "ticker": {"type": "string", "description": "The stock ticker symbol."} |
| }, |
| "required": ["ticker"] |
| } |
| }, |
| { |
| "name": "get_recent_news", |
| "description": "Get recent news for a given ticker symbol.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "ticker": {"type": "string", "description": "The stock ticker symbol."} |
| }, |
| "required": ["ticker"] |
| } |
| }, |
| { |
| "name": "get_stock_performance", |
| "description": "Get stock performance metrics for a given ticker symbol.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "ticker": {"type": "string", "description": "The stock ticker symbol."} |
| }, |
| "required": ["ticker"] |
| } |
| } |
| ] |
|
|
| |
| stock_ticker = {"value": None} |
|
|
| |
| def stock_chat(conversation): |
| try: |
| |
| system_prompt = """ |
| You are a financial assistant that provides stock information. Users might refer to companies by name or ticker symbol. |
| When necessary, determine the correct ticker symbol from the company name. Provide responses that mix numerical data and narrative descriptions. |
| """ |
|
|
| |
| messages = [{"role": "system", "content": system_prompt}] + conversation |
|
|
| |
| response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=messages, |
| functions=functions, |
| function_call="auto" |
| ) |
|
|
| message = response['choices'][0]['message'] |
|
|
| |
| if message.get("function_call"): |
| function_name = message["function_call"]["name"] |
| function_args = json.loads(message["function_call"]["arguments"]) |
|
|
| |
| ticker = function_args.get("ticker") |
| if not ticker: |
| |
| company_name = get_company_name_from_conversation(conversation) |
| if not company_name: |
| |
| return "I'm sorry, I couldn't determine the ticker symbol for the company you're referring to. Could you please provide the ticker symbol or the full company name?" |
|
|
| |
| return handle_no_stock_found(company_name) |
|
|
| |
| stock_ticker["value"] = ticker |
|
|
| |
| if function_name == "get_full_stock_report": |
| report = get_full_stock_report(ticker) |
| if not report.get("overview"): |
| return "I'm sorry, I couldn't retrieve the full stock report. Please check the ticker symbol and try again." |
| formatted_report = format_stock_report(report) |
| |
| conversation.append({"role": "function", "name": function_name, "content": formatted_report}) |
|
|
| |
| final_response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=conversation |
| ) |
| assistant_message = final_response['choices'][0]['message']['content'] |
| |
| conversation.append({"role": "assistant", "content": assistant_message}) |
| return assistant_message |
|
|
| elif function_name == "get_company_overview": |
| overview = get_company_overview(ticker) |
| if not overview: |
| return "I'm sorry, I couldn't retrieve the company overview. Please check the ticker symbol and try again." |
| formatted_overview = f""" |
| **Company Overview for {ticker}** |
| - **Company Name:** {overview.get('company_name', 'N/A')} |
| - **Industry:** {overview.get('industry', 'N/A')} |
| - **CEO:** {overview.get('ceo', 'N/A')} |
| - **Description:** {overview.get('description', 'N/A')} |
| """ |
| conversation.append({"role": "function", "name": function_name, "content": formatted_overview}) |
|
|
| final_response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=conversation |
| ) |
| assistant_message = final_response['choices'][0]['message']['content'] |
| conversation.append({"role": "assistant", "content": assistant_message}) |
| return assistant_message |
|
|
| elif function_name == "get_financial_metrics": |
| metrics = get_financial_metrics(ticker) |
| if not metrics: |
| return "I'm sorry, I couldn't retrieve the financial metrics. Please check the ticker symbol and try again." |
| formatted_metrics = f""" |
| **Financial Metrics for {ticker}** |
| - **Market Cap:** {metrics.get('market_cap', 'N/A')} |
| - **Enterprise Value:** {metrics.get('enterprise_value', 'N/A')} |
| - **Shares Outstanding:** {metrics.get('shares_outstanding', 'N/A')} |
| - **Total Revenue:** {metrics.get('total_revenue', 'N/A')} |
| - **Employees:** {metrics.get('employees', 'N/A')} |
| - **Gross Profit Margin:** {metrics.get('gross_profit_margin', 'N/A')} |
| - **EBITDA Margin:** {metrics.get('ebitda_margin', 'N/A')} |
| - **Operating Margin:** {metrics.get('operating_margin', 'N/A')} |
| - **Net Profit Margin:** {metrics.get('net_profit_margin', 'N/A')} |
| - **EPS Diluted:** {metrics.get('eps_diluted', 'N/A')} |
| - **P/E Ratio:** {metrics.get('pe_ratio', 'N/A')} |
| - **Forward P/E Ratio:** {metrics.get('forward_pe_ratio', 'N/A')} |
| |
| **Financial Health** |
| - **Cash:** {metrics.get('cash', 'N/A')} |
| - **Net Debt:** {metrics.get('net_debt', 'N/A')} |
| - **Debt/Equity:** {metrics.get('debt_to_equity', 'N/A')} |
| - **EBIT/Interest:** {metrics.get('ebit_to_interest', 'N/A')} |
| |
| **Dividends** |
| - **Yield:** {metrics.get('dividendYield', 'N/A')} |
| - **Payout Ratio:** {metrics.get('payoutRatio', 'N/A')} |
| - **DPS:** {metrics.get('dividendRate', 'N/A')} |
| """ |
| conversation.append({"role": "function", "name": function_name, "content": formatted_metrics}) |
|
|
| final_response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=conversation |
| ) |
| assistant_message = final_response['choices'][0]['message']['content'] |
| conversation.append({"role": "assistant", "content": assistant_message}) |
| return assistant_message |
|
|
| elif function_name == "get_recent_news": |
| news_items = get_recent_news(ticker) |
| if not news_items: |
| return "I'm sorry, I couldn't retrieve recent news for this ticker." |
| formatted_news = f"**Recent News for {ticker}**\n" |
| for item in news_items: |
| formatted_news += f"- [{item.get('title', 'N/A')}]({item.get('link', '#')}) ({item.get('publisher', 'N/A')}) - {item.get('published_time', 'N/A')}\n" |
| conversation.append({"role": "function", "name": function_name, "content": formatted_news}) |
|
|
| final_response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=conversation |
| ) |
| assistant_message = final_response['choices'][0]['message']['content'] |
| conversation.append({"role": "assistant", "content": assistant_message}) |
| return assistant_message |
|
|
| elif function_name == "get_stock_performance": |
| performance = get_stock_performance(ticker) |
| if not performance: |
| return "I'm sorry, I couldn't retrieve the stock performance metrics." |
| formatted_performance = f""" |
| **Stock Performance for {ticker}** |
| - **Current Price:** {performance.get('current_price', 'N/A')} |
| - **52-Week Range:** {performance.get('52_week_range', 'N/A')} |
| - **YTD Return:** {performance.get('ytd_return', 'N/A')} |
| - **1-Year Total Return:** {performance.get('1y_total_return', 'N/A')} |
| - **5-Year Total Return CAGR:** {performance.get('5y_total_return_cagr', 'N/A')} |
| - **10-Year Total Return CAGR:** {performance.get('10y_total_return_cagr', 'N/A')} |
| """ |
| conversation.append({"role": "function", "name": function_name, "content": formatted_performance}) |
|
|
| final_response = openai.ChatCompletion.create( |
| model="gpt-3.5-turbo", |
| messages=conversation |
| ) |
| assistant_message = final_response['choices'][0]['message']['content'] |
| conversation.append({"role": "assistant", "content": assistant_message}) |
| return assistant_message |
|
|
| else: |
| return "I'm sorry, I couldn't process your request." |
| else: |
| |
| assistant_response = message.get("content") |
| conversation.append({"role": "assistant", "content": assistant_response}) |
| return assistant_response |
|
|
| except Exception as e: |
| print(f"Error in stock chat: {e}") |
| return "I'm sorry, something went wrong while processing your request. Could you please try again?" |
|
|
| |
| def chat(user_input, history): |
| if history is None: |
| history = [] |
| |
| conversation = [] |
| for user_msg, assistant_msg in history: |
| conversation.append({"role": "user", "content": user_msg}) |
| conversation.append({"role": "assistant", "content": assistant_msg}) |
| |
| conversation.append({"role": "user", "content": user_input}) |
| |
| assistant_response = stock_chat(conversation) |
| |
| history.append((user_input, assistant_response)) |
| return history, history |
|
|
| |
| def display_stock_insight(ticker): |
| if not ticker: |
| return "Kindly mention a stock ticker in chat to view the details" |
| |
| overview = get_company_overview(ticker) |
| financials = get_financial_metrics(ticker) |
| performance = get_stock_performance(ticker) |
|
|
| |
| if not overview: |
| return "Kindly mention a stock ticker in chat to view the details" |
|
|
| |
| website = overview.get('website') |
| website_display = f"[{website}](https://{website})" if website else "N/A" |
|
|
| |
| stock_insight_content = f""" |
| ### Company Overview |
| - **Name:** {overview.get('company_name', 'N/A')} |
| - **CEO:** {overview.get('ceo', 'N/A')} |
| - **Website:** {website_display} |
| - **Sector:** {overview.get('industry', 'N/A')} |
| - **Year Founded:** {overview.get('year_founded', 'N/A')} |
| |
| ### Profile |
| - **Market Cap:** {financials.get('market_cap', 'N/A')} |
| - **EV:** {financials.get('enterprise_value', 'N/A')} |
| - **Shares Out:** {financials.get('shares_outstanding', 'N/A')} |
| - **Revenue:** {financials.get('total_revenue', 'N/A')} |
| - **Employees:** {financials.get('employees', 'N/A')} |
| |
| ### Margins |
| - **Gross Margin:** {financials.get('gross_profit_margin', 'N/A')} |
| - **EBITDA Margin:** {financials.get('ebitda_margin', 'N/A')} |
| - **Operating Margin:** {financials.get('operating_margin', 'N/A')} |
| - **Net Profit Margin:** {financials.get('net_profit_margin', 'N/A')} |
| |
| ### Stock Performance |
| - **Current Price:** {performance.get('current_price', 'N/A')} |
| - **52-Week Range:** {performance.get('52_week_range', 'N/A')} |
| - **YTD Return:** {performance.get('ytd_return', 'N/A')} |
| - **1-Year Total Return:** {performance.get('1y_total_return', 'N/A')} |
| |
| ### Financial Health |
| - **Cash:** {financials.get('cash', 'N/A')} |
| - **Net Debt:** {financials.get('net_debt', 'N/A')} |
| - **Debt/Equity:** {financials.get('debt_to_equity', 'N/A')} |
| - **EBIT/Interest:** {financials.get('ebit_to_interest', 'N/A')} |
| |
| ### Growth (CAGR) |
| - **Revenue 3Yr:** {financials.get('revenue_3yr_cagr', 'N/A')} |
| - **EPS Diluted 3Yr:** {financials.get('eps_diluted_3yr_cagr', 'N/A')} |
| |
| ### Dividends |
| - **Yield:** {financials.get('dividendYield', 'N/A')} |
| - **Payout Ratio:** {financials.get('payoutRatio', 'N/A')} |
| - **DPS:** {financials.get('dividendRate', 'N/A')} |
| |
| **Description:** {overview.get('description', 'N/A')} |
| """ |
| return stock_insight_content |
|
|
| |
| def update_stock_insight(history): |
| try: |
| if not history: |
| ticker = stock_ticker["value"] |
| else: |
| ticker = stock_ticker["value"] |
|
|
| if not ticker: |
| |
| fig = go.Figure() |
| fig.update_layout( |
| title="No stock ticker selected.", |
| xaxis_title="Date", |
| yaxis_title="Price (USD)", |
| template="plotly_white" |
| ) |
| return fig, "No stock ticker selected." |
|
|
| |
| content = display_stock_insight(ticker) |
|
|
| |
| fig = create_stock_chart(ticker) |
|
|
| return fig, content |
| except Exception as e: |
| print(f"Error updating stock insight: {e}") |
| |
| fig = go.Figure() |
| fig.update_layout( |
| title="Error generating stock insight.", |
| xaxis_title="Date", |
| yaxis_title="Price (USD)", |
| template="plotly_white" |
| ) |
| return fig, "I think the information you are looking could be provided quickly if you could provid me a ticker or company name" |
|
|
| |
| def chat(user_input, history): |
| if history is None: |
| history = [] |
| |
| conversation = [] |
| for user_msg, assistant_msg in history: |
| conversation.append({"role": "user", "content": user_msg}) |
| conversation.append({"role": "assistant", "content": assistant_msg}) |
| |
| conversation.append({"role": "user", "content": user_input}) |
| |
| assistant_response = stock_chat(conversation) |
| |
| history.append((user_input, assistant_response)) |
| return history, history |
|
|
|
|
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| with gr.Blocks(css=""" |
| /* Custom CSS for White Chat Background and Enhanced Appearance */ |
| |
| /* Style the entire Gradio container */ |
| .gradio-container { |
| background-color: #E3F4F4; /* White background for the entire application */ |
| color: #000000; /* Black text by default */ |
| font-family: 'Roboto', sans-serif; /* Default font family */ |
| } |
| |
| /* Style individual chat messages */ |
| .chatbot .message { |
| background-color: #ffffff; /* White background for messages */ |
| border-radius: 10px; |
| padding: 10px; |
| margin-bottom: 10px; |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */ |
| } |
| |
| /* Differentiate user and assistant messages with border accents */ |
| .chatbot .message.user { |
| border-left: 4px solid #6c757d; /* Grey accent for user messages */ |
| } |
| |
| .chatbot .message.assistant { |
| border-left: 4px solid #6c757d; /* Grey accent for assistant messages */ |
| } |
| |
| /* Optional: Style the chat scrollbar */ |
| .chatbot .scroll-container::-webkit-scrollbar { |
| width: 8px; |
| } |
| .chatbot .scroll-container::-webkit-scrollbar-track { |
| background: #f1f1f1; |
| } |
| .chatbot .scroll-container::-webkit-scrollbar-thumb { |
| background: #888; |
| border-radius: 4px; |
| } |
| .chatbot .scroll-container::-webkit-scrollbar-thumb:hover { |
| background: #555; |
| } |
| |
| /* Style the Stock Insight section */ |
| #stock_insight_section { |
| background-color: #ffffff; /* White background */ |
| color: #3A98B9; /* Dark gray text for general content */ |
| padding: 15px; |
| border-radius: 10px; |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */ |
| } |
| |
| /* Stock Insight Content Styles */ |
| #stock_insight_section h3 { |
| color: #3A98B9; /* Bright Blue for Subheadings */ |
| font-family: 'Montserrat', sans-serif; /* Accent Font for Subheadings */ |
| } |
| |
| /* Animation for the textbox placeholder chat bot window background */ |
| .dark .bubble-wrap.svelte-1e1jlin.svelte-1e1jlin.svelte-1e1jlin { |
| background: #fff !important; |
| } |
| |
| |
| /* Animation for the textbox placeholder chat bot input box */ |
| .block.svelte-12cmxck { |
| background: #fff !important; |
| } |
| |
| /* Change the loading overlay background color to white */ |
| .loading-container { |
| background-color: #ffffff !important; /* White background */ |
| } |
| |
| |
| |
| /* Animation for the textbox placeholder chat bot input box text color*/ |
| textarea.svelte-1f354aw.svelte-1f354aw { |
| background: #fff !important; |
| color: #000 !important; |
| } |
| |
| |
| #stock_insight_section p, |
| #stock_insight_section li { |
| color: #1A3636; /* Darker Gray for Paragraphs and List Items */ |
| font-size: 14px; /* Font Size for Paragraphs and List Items */ |
| line-height: 1.6; /* Line Height for Better Readability */ |
| } |
| |
| /* Animation for the textbox placeholder */ |
| @keyframes placeholderMove { |
| 0% { |
| opacity: 0; |
| transform: translateX(0); |
| } |
| 15% { |
| opacity: 1; |
| transform: translateX(10px); |
| } |
| 10% { |
| opacity: 0; |
| transform: translateX(-10px); |
| } |
| } |
| |
| /* added after upendra help */ |
| .gradio-container-4-44-1 b, .gradio-container-4-44-1 strong, center { |
| color: #000 !important; |
| } |
| .animated-placeholder::placeholder { |
| animation: placeholderMove 4s infinite; |
| color: #6c757d; /* Grey color for placeholder text */ |
| font-style: italic; /* Italic Text */ |
| } |
| """) as demo: |
| gr.Markdown("<h1><center>Talk 2 Stock</center></h1>") |
| with gr.Row(): |
| with gr.Column(scale=6): |
| gr.Markdown("<h2><center>Chat Xchange</center></h2>") |
| chatbot = gr.Chatbot() |
| state = gr.State([]) |
| with gr.Row(): |
| txt = gr.Textbox( |
| show_label=False, |
| placeholder="Hey Trader, Let's chatch up with Stocks", |
| elem_classes="animated-placeholder" |
| ) |
| txt.submit(chat, inputs=[txt, state], outputs=[chatbot, state]) |
| txt.submit(lambda: "", None, txt) |
| with gr.Column(scale=4): |
| gr.Markdown("<h2><center>Stock Insight</center></h2>") |
| with gr.Column(elem_id="stock_insight_section"): |
| stock_chart = gr.Plot() |
| stock_insight = gr.Markdown() |
| |
| state.change( |
| update_stock_insight, |
| inputs=state, |
| outputs=[stock_chart, stock_insight] |
| ) |
|
|
| |
| demo.launch() |
|
|
|
|