File size: 4,289 Bytes
c0c59ce
 
 
85b7a89
f77f56c
 
958b14a
 
 
011359b
ada01c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f77f56c
ada01c4
 
 
 
 
f77f56c
ada01c4
f77f56c
 
ada01c4
 
f77f56c
ada01c4
 
 
f77f56c
ada01c4
 
 
 
45ab29a
 
 
 
 
 
 
 
 
 
0424c3b
ada01c4
 
 
f77f56c
ada01c4
 
 
 
 
 
 
f77f56c
976b979
261a5a7
ada01c4
 
976b979
c40f5aa
0424c3b
976b979
 
ada01c4
 
 
0424c3b
 
 
ada01c4
5b98dcd
976b979
5b98dcd
 
c40f5aa
976b979
5b98dcd
976b979
 
 
 
 
 
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
98
99
100
101
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)

# 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}")