File size: 3,754 Bytes
c0c59ce
 
 
85b7a89
f77f56c
 
958b14a
 
 
011359b
ada01c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f77f56c
ada01c4
 
 
 
 
f77f56c
ada01c4
f77f56c
 
ada01c4
 
f77f56c
ada01c4
 
 
f77f56c
ada01c4
 
 
 
 
 
 
f77f56c
ada01c4
 
 
 
 
 
 
f77f56c
ada01c4
 
 
 
c40f5aa
 
 
5b98dcd
c40f5aa
5b98dcd
 
c40f5aa
5b98dcd
 
ada01c4
 
 
 
 
5b98dcd
 
 
 
c40f5aa
 
 
5b98dcd
 
 
c40f5aa
85b7a89
 
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
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")
    # 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
    def color_combined_score(value):
        color = 'green' if value > 0 else 'red' if value < 0 else 'none'
        return f'background-color: {color};'

    # Use 'Styler' to apply the style function to the 'Combined Score' column
    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")
    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 the company name and ticker symbol
            st.write(f"**{info.get('longName')}** ({ticker_symbol})")
            st.write(info.get('longBusinessSummary'))
            
            # Display each financial ratio and its comparison result
            for ratio, status in comparison.items():
                st.write(f"{ratio}: {status}")