import streamlit as st import requests import re import torch from transformers import BertTokenizer, BertForSequenceClassification # Load tokenizer and model tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') model_path = '/Users/kartikrathi/Documents/News_sentiment_analysis/model' model = BertForSequenceClassification.from_pretrained(model_path) # Function to analyze sentiment def analyze_sentiment(text): # Tokenize inputs inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512) # Perform inference with torch.no_grad(): outputs = model(**inputs) # Get predicted logits logits = outputs.logits # Determine predicted sentiment predicted_class_id = torch.argmax(logits, dim=1).item() sentiment = {0: "positive", 1: "negative", 2: "neutral"} return sentiment[predicted_class_id] # Function to fetch news using an API def fetch_stock_news(symbol): api_token = '6679177763bcd9.48465511' # Replace with your actual API token url = f'https://eodhd.com/api/news?s={symbol}&offset=0&limit=2&api_token={api_token}&fmt=json' try: response = requests.get(url) response.raise_for_status() # Raise exception for bad status codes data = response.json() news_list = [] for article in data: title = article.get('title', 'Title not available') content = article.get('content', 'Content not available') url = article.get('url', 'URL not available') date = article.get('date', 'Date not available') # Remove unwanted sections from content cleaned_content = remove_sections(content) news_list.append({'title': title, 'content': cleaned_content, 'url': url, 'date': date}) return news_list except requests.exceptions.RequestException as e: print(f"Error fetching news for {symbol}: {e}") return None # Function to remove unwanted sections def remove_sections(content): # Patterns to remove patterns = [ r'About\s+.*?[\n\r]+', # 'About {stock}' section r'Safe\s+Harbor.*', # 'Safe Harbor' section r'Story\s+continues.*', # 'Story continues' r'Visit\s+www\.infosys\.com.*', # 'Visit www.infosys.com...' r'Logo', # 'Logo' ] for pattern in patterns: content = re.sub(pattern, '', content, flags=re.IGNORECASE) return content.strip() # Streamlit app with multi-page support def main(): st.sidebar.title('Navigation') page = st.sidebar.radio("Go to", ('Home', 'Portfolio & News')) if page == 'Home': st.title("Financial News Sentiment Analysis") st.markdown(""" This app performs sentiment analysis on financial news using FinBERT model. """) # Input text box for user input user_input = st.text_area("Enter your financial news text here:", height=200) # Perform sentiment analysis when user clicks the button if st.button("Analyze"): if user_input: sentiment = analyze_sentiment(user_input) if sentiment == "positive": st.markdown(f"
{sentiment}
", unsafe_allow_html=True) elif sentiment == "negative": st.markdown(f"{sentiment}
", unsafe_allow_html=True) elif sentiment == "neutral": st.markdown(f"{sentiment}
", unsafe_allow_html=True) else: st.warning("Please enter some text.") elif page == 'Portfolio & News': st.title('Portfolio & News') # Sidebar to manage portfolio and fetch news st.sidebar.subheader('Manage Portfolio & Fetch News') st.sidebar.info("Enter your portfolio/company names here to fetch news.") # Input fields for portfolio management and news fetching portfolio = st.sidebar.text_area("Enter your portfolio/company names (one per line):", height=200) if st.sidebar.button("Save"): # Add ".NSE" suffix to each company name shares = portfolio.split("\n") shares = [share.strip() + ".NSE" for share in shares if share.strip()] st.sidebar.markdown("**Shares**") st.sidebar.markdown("\n".join(shares)) # Button to fetch news and perform sentiment analysis if st.sidebar.button("Fetch News & Analyze Sentiment"): if portfolio: companies = portfolio.split("\n") companies = [company.strip() + ".NSE" for company in companies if company.strip()] for company in companies: st.subheader(f"Latest News for {company}:") news = fetch_stock_news(company) if news: for article in news: title = article['title'] content = article['content'] url = article['url'] date = article['date'] st.markdown(f"**Title:** [{title}]({url}) ({date})", unsafe_allow_html=True) # Display a truncated version of the content truncated_content = content[:200] + "..." st.markdown(f"**Content:** {truncated_content}") # Expander for full content with st.expander("Expand more"): st.markdown(f"{content}") st.markdown("---") # Analyze sentiment of news content (assuming content is available) if content: sentiment = analyze_sentiment(content) if sentiment == "positive": sentiment_color = "green" elif sentiment == "negative": sentiment_color = "red" elif sentiment == "neutral": sentiment_color = "blue" st.markdown(f"**Sentiment:** {sentiment}", unsafe_allow_html=True) st.markdown("---") else: st.warning(f"No news articles found for {company}.") else: st.warning("Please enter portfolio/company names to fetch news.") if __name__ == '__main__': main()