os1187's picture
Update app.py
0424c3b verified
raw
history blame
3.66 kB
import streamlit as st
import yfinance as yf
import pandas as pd
# Correctly using st.cache_data as per Streamlit's new caching mechanism
@st.cache_data
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)
# 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([1, 3])
with col1:
st.subheader("Stock Overview")
# 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
st.dataframe(scores_df_sorted.style.applymap(color_combined_score, subset=['Combined Score']))
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, info = fetch_stock_data(ticker_symbol)
comparison, _ = compare_to_index(stock_data, sp500_averages)
# Display the company name and ticker symbol
st.write(f"**{info.get('longName', 'N/A')}** ({ticker_symbol})")
st.write(info.get('longBusinessSummary', 'Description not available.'))
# Display each financial ratio and its comparison result
for ratio, status in comparison.items():
st.text(f"{ratio}: {status}")