Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -77,5 +77,98 @@ with col2:
|
|
77 |
|
78 |
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
|
|
|
77 |
|
78 |
|
79 |
|
80 |
+
import streamlit as st
|
81 |
+
import yfinance as yf
|
82 |
+
import pandas as pd
|
83 |
+
|
84 |
+
# Define the path to your CSV file with S&P 500 averages
|
85 |
+
sp500_averages_path = 'sp500_averages.csv'
|
86 |
+
|
87 |
+
# Define the function to load S&P 500 averages from a CSV file
|
88 |
+
@st.experimental_memo
|
89 |
+
def get_sp500_list():
|
90 |
+
table = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
|
91 |
+
return table[0]['Symbol'].tolist()
|
92 |
+
|
93 |
+
# Define the function to load S&P 500 averages from a CSV file
|
94 |
+
sp500_averages_path = 'sp500_averages.csv'
|
95 |
+
def load_sp500_averages(filepath):
|
96 |
+
return pd.read_csv(filepath, header=0, names=['Ratio', 'Average']).set_index('Ratio')
|
97 |
+
|
98 |
+
# Define the function to fetch financial data for a single stock
|
99 |
+
def fetch_stock_data(ticker_symbol):
|
100 |
+
ticker = yf.Ticker(ticker_symbol)
|
101 |
+
info = ticker.info
|
102 |
+
financials = {
|
103 |
+
'P/E Ratio': info.get('forwardPE'),
|
104 |
+
'P/B Ratio': info.get('priceToBook'),
|
105 |
+
'P/S Ratio': info.get('priceToSalesTrailing12Months'),
|
106 |
+
'Debt to Equity Ratio': info.get('debtToEquity'),
|
107 |
+
'Return on Equity': info.get('returnOnEquity'),
|
108 |
+
'Book-to-Market Ratio': 1 / info.get('priceToBook') if info.get('priceToBook') else None
|
109 |
+
}
|
110 |
+
return financials
|
111 |
+
|
112 |
+
# Define the function to compare stock ratios to S&P 500 averages
|
113 |
+
def compare_to_index(stock_ratios, index_averages):
|
114 |
+
comparison = {}
|
115 |
+
score = 0
|
116 |
+
for ratio, value in stock_ratios.items():
|
117 |
+
if pd.notna(value):
|
118 |
+
average = index_averages.loc[ratio, 'Average']
|
119 |
+
if value < average: # For ratios where lower is better
|
120 |
+
comparison[ratio] = 'Undervalued'
|
121 |
+
score += 1
|
122 |
+
elif value > average: # For ratios where higher is not better
|
123 |
+
comparison[ratio] = 'Overvalued'
|
124 |
+
score -= 1
|
125 |
+
else:
|
126 |
+
comparison[ratio] = 'Data not available'
|
127 |
+
return comparison, score
|
128 |
+
|
129 |
+
# Define the function to calculate combined scores for stocks
|
130 |
+
def calculate_combined_scores_for_stocks(stocks, index_averages):
|
131 |
+
scores = []
|
132 |
+
for ticker_symbol in stocks:
|
133 |
+
stock_data = fetch_stock_data(ticker_symbol)
|
134 |
+
comparison, score = compare_to_index(stock_data, index_averages)
|
135 |
+
scores.append({'Stock': ticker_symbol, 'Combined Score': score})
|
136 |
+
return pd.DataFrame(scores)
|
137 |
+
|
138 |
+
# User interface in Streamlit
|
139 |
+
st.title('S&P 500 Stock Comparison Tool')
|
140 |
+
|
141 |
+
# Fetch the current S&P 500 list and load the averages
|
142 |
+
sp500_list = get_sp500_list()
|
143 |
+
sp500_averages = load_sp500_averages(sp500_averages_path)
|
144 |
+
|
145 |
+
# Calculate combined scores for all S&P 500 stocks
|
146 |
+
scores_df = calculate_combined_scores_for_stocks(sp500_list, sp500_averages)
|
147 |
+
scores_df_sorted = scores_df.sort_values(by='Combined Score', ascending=False)
|
148 |
+
|
149 |
+
# Use columns for side-by-side layout
|
150 |
+
col1, col2 = st.columns([1, 3])
|
151 |
+
|
152 |
+
# First column for the sorted overview
|
153 |
+
with col1:
|
154 |
+
st.subheader("Stock Overview")
|
155 |
+
st.dataframe(scores_df_sorted.style.applymap(lambda x: 'background-color: green' if x > 0
|
156 |
+
else ('background-color: red' if x < 0 else '')))
|
157 |
+
|
158 |
+
# Second column for detailed financial ratios and company information
|
159 |
+
with col2:
|
160 |
+
st.subheader("Stock Details")
|
161 |
+
ticker_symbol = st.selectbox('Select a stock for details', options=sp500_list)
|
162 |
+
if ticker_symbol:
|
163 |
+
with st.spinner(f'Fetching data for {ticker_symbol}...'):
|
164 |
+
stock_data = fetch_stock_data(ticker_symbol)
|
165 |
+
comparison, _ = compare_to_index(stock_data, sp500_averages)
|
166 |
+
|
167 |
+
st.write(f"**{ticker_symbol} - {yf.Ticker(ticker_symbol).info['longName']}**")
|
168 |
+
st.write("Financial Ratios compared to S&P 500 averages:")
|
169 |
+
for ratio, status in comparison.items():
|
170 |
+
st.write(f"{ratio}: {status}")
|
171 |
+
|
172 |
+
|
173 |
|
174 |
|