File size: 3,794 Bytes
c0c59ce
 
 
85b7a89
602a247
958b14a
 
 
011359b
ada01c4
 
 
 
 
 
 
602a247
 
 
 
 
 
ada01c4
f77f56c
ada01c4
 
 
 
 
f77f56c
ada01c4
f77f56c
 
ada01c4
 
 
 
 
f77f56c
ada01c4
 
 
 
45ab29a
 
 
 
 
 
94126ed
45ab29a
0424c3b
94126ed
602a247
 
 
 
 
ada01c4
94126ed
55e99f6
ada01c4
94126ed
ada01c4
 
94126ed
ada01c4
94126ed
 
55e99f6
94126ed
261a5a7
ada01c4
 
94126ed
55e99f6
ada01c4
 
 
94126ed
0424c3b
ada01c4
5b98dcd
94126ed
5b98dcd
 
94126ed
 
5b98dcd
94126ed
 
976b979
94126ed
 
 
602a247
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import streamlit as st
import yfinance as yf
import pandas as pd

@st.cache_resource
def get_sp500_list():
    table = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
    return table[0]['Symbol'].tolist()

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', None),
        'P/B Ratio': info.get('priceToBook', None),
        'P/S Ratio': info.get('priceToSalesTrailing12Months', None),
        'Debt to Equity Ratio': info.get('debtToEquity', None),
        'Return on Equity': info.get('returnOnEquity', None),
        'Book-to-Market Ratio': 1 / info.get('priceToBook', float('nan')) 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

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)

def color_combined_score(value):
    if value > 0:
        color = 'green'
    elif value < 0:
        color = 'red'
    else:
        color = 'lightgrey'
    return f'background-color: {color};'

def filter_incomplete_stocks(df, required_columns):
    # Ensure all required columns exist in the DataFrame
    for column in required_columns:
        if column not in df.columns:
            df[column] = pd.NA
    return df.dropna(subset=required_columns)

st.title('S&P 500 Stock Comparison Tool')

sp500_list = get_sp500_list()
sp500_averages = load_sp500_averages('sp500_averages.csv')

scores_df = calculate_combined_scores_for_stocks(sp500_list, sp500_averages)
required_columns = ['P/E Ratio', 'P/B Ratio', 'P/S Ratio', 'Debt to Equity Ratio', 'Return on Equity', 'Book-to-Market Ratio']

scores_df_filtered = filter_incomplete_stocks(scores_df, required_columns)
scores_df_sorted = scores_df_filtered.sort_values(by='Combined Score', ascending=False)

col1, col2 = st.columns([3, 5])

with col1:
    st.subheader("Stock Overview")
    styled_scores_df = scores_df_sorted.style.applymap(color_combined_score, subset=['Combined Score'])
    st.dataframe(styled_scores_df)

with col2:
    st.subheader("Stock Details")
    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)
            
            st.write(f"**{info.get('longName', 'N/A')}** ({ticker_symbol})")
            st.write(info.get('longBusinessSummary', 'N/A'))
            
            for ratio in required_columns:
                value = stock_data.get(ratio, 'N/A')
                average = sp500_averages.loc[ratio, 'Average'] if ratio in sp500_averages.index else 'N/A'
                status = comparison.get(ratio, 'N/A')
                st.write(f"{ratio}: {value} (Your Ratio) | {average} (S&P 500 Avg) - {status}")