| | 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() |
| |
|
| |
|