import streamlit as st import yfinance as yf import pandas as pd import matplotlib.pyplot as plt import streamlit.components.v1 as components # Set the page to wide mode and specify a title st.set_page_config(layout="wide", page_title="Stock Insight Explorer", page_icon=":chart_with_upwards_trend:") # Display the application title in the app itself st.title('Stock Insight Explorer: Visual Analytics & Dividend Overview') # Input field for stock symbol stock_symbol = st.text_input('Enter Stock Symbol', value='JEPI') # Fetch stock data stock_data = yf.Ticker(stock_symbol) # Get historical data for the past year end_date = pd.Timestamp.today() start_date = end_date - pd.DateOffset(years=1) historical_data = stock_data.history(start=start_date, end=end_date) # Display company name and current stock price in bold company_name = stock_data.info['longName'] current_price = historical_data['Close'].iloc[-1] # st.markdown(f"**Company Name:** {company_name}") # https://finance.yahoo.com/quote/JEPQ?.tsrc=fin-srch company_url = f"https://finance.yahoo.com/quote/{stock_symbol}?.tsrc=fin-srch" # Use HTML anchor tag to create a hyperlink st.markdown(f"**Company Name:** {company_name}", unsafe_allow_html=True) st.markdown(f"**Current Price:** ${current_price:.2f}") # Creating 3 columns for the charts col1, col2, col3, col4 = st.columns(4) # Closing prices chart with col1: st.subheader('Closing Prices Over The Past Year') st.line_chart(historical_data['Close']) # Volume of stock trades chart with col2: st.subheader('Volume of Stock Trades Over The Past Year') st.bar_chart(historical_data['Volume']) # Calculate 20 day and 50 day moving averages historical_data['20 Day MA'] = historical_data['Close'].rolling(window=20).mean() historical_data['50 Day MA'] = historical_data['Close'].rolling(window=50).mean() # Line chart for closing price, 20 day MA, and 50 day MA with col3: st.subheader('Closing Price and Moving Averages') plt.figure(figsize=(10, 5)) plt.plot(historical_data.index, historical_data['Close'], label='Close Price') plt.plot(historical_data.index, historical_data['20 Day MA'], label='20 Day MA') plt.plot(historical_data.index, historical_data['50 Day MA'], label='50 Day MA') plt.legend() plt.xlabel('Date') plt.ylabel('Price') plt.title('Closing Price, 20 Day MA, and 50 Day MA') st.pyplot(plt) # Get the dividend data # Assuming stock_data is your Ticker object from yfinance dividends = stock_data.dividends # Check if there are any dividends if not dividends.empty: last_dividend_value = dividends.iloc[-1] # Get the last dividend value from the dividends history else: # Fallback to the lastDividendValue from the .info attribute if no historical dividends are found last_dividend_value = stock_data.info.get('lastDividendValue', 0) with col4: st.subheader('Dividends') markdown_output = "" # Initialize an empty string to accumulate messages # Ensure dividends.index is in the correct format dividends.index = pd.to_datetime(dividends.index).date if not dividends.empty: plt.figure(figsize=(10, 5)) dividends.plot(kind='bar') plt.title(f'Dividends of {stock_symbol} Over Time') plt.ylabel('Dividend Amount') plt.xlabel('Date') plt.xticks(rotation=45) plt.tight_layout() st.pyplot(plt) # Calculate total annual dividends today = pd.to_datetime("today") last_year_dividends = dividends.loc[dividends.index > (today - pd.DateOffset(years=1)).date()] total_annual_dividends = last_year_dividends.sum() if current_price and current_price > 0: annual_dividend_yield = (total_annual_dividends / current_price) * 100 markdown_output += f"**Annual Dividend Yield:** {annual_dividend_yield:.2f}%.\n" else: markdown_output += "Current price not available. Cannot calculate annual dividend yield.\n" else: markdown_output += "This stock does not have any dividend data available.\n" total_annual_dividends = 0 # Define it as 0 if there are no dividends if current_price and current_price > 0 and last_dividend_value: dividend_yield = (last_dividend_value / current_price) * 100 markdown_output += f"**Last Dividend Yield:** {dividend_yield:.2f}%, ${last_dividend_value:.2f} per share." else: markdown_output += "Cannot calculate last dividend yield." # Display all collected information in one markdown output st.markdown(markdown_output, unsafe_allow_html=True) # components.iframe("https://duckduckgo.com/?q=ZIM&va=i&t=hd&iar=news&df=w&ia=news") # components.iframe("https://news.google.com/rss/search?q=ZIM&hl=en-US&gl=US&ceid=US%3Aen", height=800, scrolling=True) # components.iframe("https://truevis.com", height=800, scrolling=True) from unicodedata import normalize from bs4 import BeautifulSoup from feedparser import parse as parse_feed def flatten_unicode_keys(entry_properties): """Ensures passing unicode keywords to **kwargs.""" new_properties = {} for key, value in entry_properties.items(): key_str = key.decode('utf-8') if isinstance(key, bytes) else key new_key = normalize('NFKD', key_str).encode('ascii', 'ignore').decode('ascii') # Decode the bytes object to string new_properties[new_key] = value return new_properties TEMPLATE = """

{title}

{title} {description} """ def entry_to_html(entry_id, **kwargs): new_kwargs = flatten_unicode_keys(kwargs) new_kwargs.setdefault('title', 'No title') new_kwargs.setdefault('link', 'No link') new_kwargs.setdefault('description', '') accordion_item = f"""
{new_kwargs['title']}

{new_kwargs['description']}

""" return accordion_item def convert_feed_to_accordion(url): feed = parse_feed(url) accordion_html = '
' for i, entry in enumerate(feed.entries): accordion_html += entry_to_html(i, **entry) accordion_html += '
' return accordion_html # Bootstrap CSS and JS must be included in the output HTML to style the accordion correctly bootstrap_includes = """ """ # Fetch and display the accordion url = f"https://news.google.com/rss/search?q={stock_symbol}&hl=en-US&gl=US&ceid=US%3Aen" # print(url) feed_accordion_html = bootstrap_includes + convert_feed_to_accordion(url) st.markdown(f"Latest news on **{stock_symbol}**") components.html(feed_accordion_html, height=800, scrolling=True) # def convert_feed_to_raw_data(url): # feed = parse_feed(url) # raw_data = [entry for entry in feed.entries] # return raw_data # Fetch and display the raw RSS data # url = f"https://news.google.com/rss/search?q={stock_symbol}&hl=en-US&gl=US&ceid=US%3Aen" # raw_data = convert_feed_to_raw_data(url) # print(raw_data) # st.write(raw_data)