import streamlit as st import yfinance as yf import pandas as pd # Define the path to your CSV file sp500_averages_path = 'sp500_averages.csv' def load_sp500_averages(filepath): # Load the CSV without specifying an index column name return pd.read_csv(filepath, header=0, names=['Ratio', 'Average']).set_index('Ratio') # Fetch financial data for a single stock def fetch_stock_data(ticker_symbol): ticker = yf.Ticker(ticker_symbol) info = ticker.info # Calculate Book-to-Market Ratio pb_ratio = info.get('priceToBook') book_to_market_ratio = 1 / pb_ratio if pb_ratio and pb_ratio > 0 else None # Extract relevant financial information, including Book-to-Market Ratio financials = { 'P/E Ratio': info.get('forwardPE'), 'P/B Ratio': pb_ratio, 'P/S Ratio': info.get('priceToSalesTrailing12Months'), 'Debt to Equity Ratio': info.get('debtToEquity'), 'Return on Equity': info.get('returnOnEquity'), 'Book-to-Market Ratio': book_to_market_ratio, } return financials, info # Update the cache decorator @st.experimental_memo def get_sp500_list(): table = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies') return table[0]['Symbol'].tolist() # Use the updated cache function and define the CSV path sp500_list = get_sp500_list() sp500_averages = load_sp500_averages(sp500_averages_path) # Calculate combined scores for stocks in the S&P 500 scores_df = calculate_combined_scores_for_stocks(sp500_list, sp500_averages) scores_df_sorted = scores_df.sort_values(by='Combined Score', ascending=False) # Use columns for side-by-side layout col1, col2 = st.columns([1, 3]) # First column for the sorted overview with col1: st.subheader("Stock Overview") # Create a DataFrame for the sidebar with color-coded combined scores scores_df_sorted['color'] = scores_df_sorted['Combined Score'].apply( lambda x: 'green' if x > 0 else 'red' if x < 0 else 'grey') for index, row in scores_df_sorted.iterrows(): color = row['color'] st.markdown(f"{row['Stock']}: {row['Combined Score']}", unsafe_allow_html=True) # Second column for detailed financial ratios and company information with col2: st.subheader("Stock Details") # Dropdown to select stock for details ticker_symbol = st.selectbox('Select a stock for details', options=sp500_list) if ticker_symbol: with st.spinner(f'Fetching data for {ticker_symbol}...'): stock_data, info = fetch_stock_data(ticker_symbol) comparison, _ = compare_to_index(stock_data, sp500_averages) # Display company name and description st.write(f"**{info.get('longName')}**") st.write(info.get('longBusinessSummary')) # Display financial ratios in a table st.table(pd.DataFrame.from_dict(stock_data, orient='index', columns=['Value'])) import streamlit as st import yfinance as yf import pandas as pd # Define the path to your CSV file with S&P 500 averages sp500_averages_path = 'sp500_averages.csv' # Define the function to load S&P 500 averages from a CSV file @st.experimental_memo def get_sp500_list(): table = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies') return table[0]['Symbol'].tolist() # Define the function to load S&P 500 averages from a CSV file sp500_averages_path = 'sp500_averages.csv' def load_sp500_averages(filepath): return pd.read_csv(filepath, header=0, names=['Ratio', 'Average']).set_index('Ratio') # Define the function to fetch financial data for a single stock def fetch_stock_data(ticker_symbol): ticker = yf.Ticker(ticker_symbol) info = ticker.info financials = { 'P/E Ratio': info.get('forwardPE'), 'P/B Ratio': info.get('priceToBook'), 'P/S Ratio': info.get('priceToSalesTrailing12Months'), 'Debt to Equity Ratio': info.get('debtToEquity'), 'Return on Equity': info.get('returnOnEquity'), 'Book-to-Market Ratio': 1 / info.get('priceToBook') if info.get('priceToBook') else None } return financials # Define the function to compare stock ratios to S&P 500 averages def compare_to_index(stock_ratios, index_averages): comparison = {} score = 0 for ratio, value in stock_ratios.items(): if pd.notna(value): average = index_averages.loc[ratio, 'Average'] if value < average: # For ratios where lower is better comparison[ratio] = 'Undervalued' score += 1 elif value > average: # For ratios where higher is not better comparison[ratio] = 'Overvalued' score -= 1 else: comparison[ratio] = 'Data not available' return comparison, score # Define the function to calculate combined scores for stocks def calculate_combined_scores_for_stocks(stocks, index_averages): scores = [] for ticker_symbol in stocks: stock_data = fetch_stock_data(ticker_symbol) comparison, score = compare_to_index(stock_data, index_averages) scores.append({'Stock': ticker_symbol, 'Combined Score': score}) return pd.DataFrame(scores) # User interface in Streamlit st.title('S&P 500 Stock Comparison Tool') # Fetch the current S&P 500 list and load the averages sp500_list = get_sp500_list() sp500_averages = load_sp500_averages(sp500_averages_path) # Calculate combined scores for all S&P 500 stocks scores_df = calculate_combined_scores_for_stocks(sp500_list, sp500_averages) scores_df_sorted = scores_df.sort_values(by='Combined Score', ascending=False) # Use columns for side-by-side layout col1, col2 = st.columns([1, 3]) # First column for the sorted overview with col1: st.subheader("Stock Overview") st.dataframe(scores_df_sorted.style.applymap(lambda x: 'background-color: green' if x > 0 else ('background-color: red' if x < 0 else ''))) # Second column for detailed financial ratios and company information with col2: st.subheader("Stock Details") ticker_symbol = st.selectbox('Select a stock for details', options=sp500_list) if ticker_symbol: with st.spinner(f'Fetching data for {ticker_symbol}...'): stock_data = fetch_stock_data(ticker_symbol) comparison, _ = compare_to_index(stock_data, sp500_averages) st.write(f"**{ticker_symbol} - {yf.Ticker(ticker_symbol).info['longName']}**") st.write("Financial Ratios compared to S&P 500 averages:") for ratio, status in comparison.items(): st.write(f"{ratio}: {status}")