Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import yfinance as yf | |
| import pandas as pd | |
| # Correctly using st.cache_data as per Streamlit's new caching mechanism | |
| 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 path to your CSV file with S&P 500 averages | |
| sp500_averages_path = 'sp500_averages.csv' | |
| def load_sp500_averages(filepath): | |
| return pd.read_csv(filepath, header=0, names=['Ratio', 'Average']).set_index('Ratio') | |
| 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, info | |
| def compare_to_index(stock_ratios, index_averages): | |
| comparison = {} | |
| score = 0 | |
| for ratio, value in stock_ratios.items(): | |
| if ratio in index_averages.index and pd.notna(value): | |
| average = index_averages.loc[ratio, 'Average'] | |
| comparison[ratio] = 'Undervalued' if value < average else 'Overvalued' | |
| score += 1 if value < average else -1 | |
| return comparison, score | |
| # Ensure this function is defined before it's called in the script | |
| 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) | |
| # Define the color-coding function for the 'Combined Score' column | |
| def color_combined_score(value): | |
| """Colors the combined score cell based on its value.""" | |
| if value > 0: | |
| color = 'green' | |
| elif value < 0: | |
| color = 'red' | |
| else: | |
| color = 'none' | |
| return f'background-color: {color};' | |
| # User interface in Streamlit | |
| st.title('S&P 500 Stock Comparison Tool') | |
| # Load the current S&P 500 list and 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) | |
| # Layout for displaying overview and details | |
| col1, col2 = st.columns([3, 5]) # For example, this will give the first column 3/8 of the width | |
| with col1: | |
| st.subheader("Stock Overview") | |
| # Make sure to convert 'Combined Score' to numeric if it's not already | |
| scores_df_sorted['Combined Score'] = pd.to_numeric(scores_df_sorted['Combined Score'], errors='coerce') | |
| # Apply color based on 'Combined Score' value and display the DataFrame | |
| styled_scores_df = scores_df_sorted.style.applymap(color_combined_score, subset=['Combined Score']) | |
| st.dataframe(styled_scores_df, height=600) | |
| with col2: | |
| st.subheader("Stock Details") | |
| # Get the sorted list of ticker symbols based on the combined score | |
| sorted_tickers = scores_df_sorted['Stock'].tolist() | |
| ticker_symbol = st.selectbox('Select a stock for details', options=sorted_tickers) | |
| 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) | |
| # Display the company name and ticker symbol | |
| st.write(f"**{ticker_symbol}**") | |
| # Display each financial ratio, its value, and the S&P 500 average | |
| for ratio in stock_data.keys(): | |
| value = stock_data[ratio] | |
| average = sp500_averages.loc[ratio, 'Average'] if ratio in sp500_averages.index else 'N/A' | |
| comparison_result = comparison[ratio] if ratio in comparison else 'N/A' | |
| st.write(f"{ratio}: {value} (Your Ratio) | {average} (S&P 500 Avg) - {comparison_result}") | |