File size: 4,712 Bytes
4128a99
 
 
 
 
 
 
ebb0187
211b3ce
d6ca9bb
4128a99
 
211b3ce
d6ca9bb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211b3ce
4128a99
 
ebb0187
4128a99
 
d6ca9bb
 
 
 
4128a99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ebb0187
4128a99
d6ca9bb
 
4128a99
d6ca9bb
4128a99
 
ebb0187
4128a99
 
d6ca9bb
 
 
4128a99
 
 
 
 
ebb0187
4128a99
211b3ce
d6ca9bb
4128a99
d6ca9bb
4128a99
0db878d
d6ca9bb
 
 
0db878d
d6ca9bb
 
 
0db878d
d6ca9bb
 
 
0db878d
d6ca9bb
 
 
0db878d
d6ca9bb
 
 
 
 
 
0db878d
d6ca9bb
 
 
 
 
0db878d
d6ca9bb
0db878d
d6ca9bb
 
211b3ce
d6ca9bb
 
 
 
 
 
 
 
 
8fae4fb
211b3ce
d6ca9bb
ebb0187
d6ca9bb
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import pandas as pd
import requests
from bs4 import BeautifulSoup
from transformers import pipeline
import logging
from datetime import datetime
import numpy as np
import gradio as gr

# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Initialize sentiment analysis model
sentiment_analyzer = None

def load_sentiment_model():
    global sentiment_analyzer
    try:
        sentiment_analyzer = pipeline("sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english")
        logger.info("Sentiment analysis model successfully initialized.")
        return "Model loaded successfully!"
    except Exception as e:
        logger.error(f"Failed to initialize sentiment analysis model: {e}")
        return f"Error loading model: {str(e)}"

# Load the model at startup
load_sentiment_model()

def scrape_finviz_news(ticker):
    """
    Scrapes news headlines for the given ticker from Finviz.
    """
    try:
        url = f"https://finviz.com/quote.ashx?t={ticker}"
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
        
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')
        news_table = soup.find(id='news-table')
        
        if not news_table:
            return [], []
        
        headlines = []
        dates = []
        for row in news_table.findAll('tr'):
            headline = row.find('a', class_='tab-link-news')
            date_data = row.find('td', align='right')
            if headline and date_data:
                headlines.append(headline.text.strip())
                date_text = date_data.text.strip().split(' ')
                date = date_text[0] if len(date_text) > 0 else datetime.now().strftime('%Y-%m-%d')
                dates.append(date)
        
        logger.info(f"Scraped {len(headlines)} headlines for {ticker}.")
        return headlines, dates
    except Exception as e:
        logger.error(f"Error scraping {ticker}: {e}")
        return [], []
    
def analyze_sentiment(headlines):
    """
    Performs sentiment analysis on headlines.
    """
    try:
        if not headlines:
            return [], []
        
        results = sentiment_analyzer(headlines)
        labels = [res['label'] for res in results]
        scores = [res['score'] for res in results]
        return labels, scores
    except Exception as e:
        logger.error(f"Sentiment analysis error: {e}")
        return [], []

def analyze_stock(ticker):
    """
    Analyzes a single stock ticker and returns results.
    """
    try:
        ticker = ticker.strip().upper()
        if not ticker:
            return "Please enter a valid ticker symbol."
        
        headlines, dates = scrape_finviz_news(ticker)
        if not headlines:
            return f"No headlines found for {ticker}."
        
        labels, scores = analyze_sentiment(headlines)
        if not labels:
            return f"Could not analyze sentiment for {ticker}."
        
        positive_count = labels.count('POSITIVE')
        negative_count = labels.count('NEGATIVE')
        average_score = np.mean([score if label == 'POSITIVE' else -score for label, score in zip(labels, scores)])
        
        # Format results as text
        result = f"## Analysis for {ticker}\n\n"
        result += f"- Headlines analyzed: {len(headlines)}\n"
        result += f"- Average sentiment score: {average_score:.4f}\n"
        result += f"- Positive headlines: {positive_count}\n"
        result += f"- Negative headlines: {negative_count}\n\n"
        
        result += "### Recent Headlines:\n\n"
        for i, (headline, date, label, score) in enumerate(zip(headlines, dates, labels, scores), 1):
            if i > 10:  # Limit to 10 headlines
                break
            result += f"{i}. [{date}] {headline} - {label} ({score:.2f})\n"
        
        return result
    except Exception as e:
        logger.error(f"Error analyzing {ticker}: {e}")
        return f"Error analyzing {ticker}: {str(e)}"

# Create a simple Gradio interface
iface = gr.Interface(
    fn=analyze_stock,
    inputs=gr.Textbox(placeholder="Enter a ticker symbol (e.g., AAPL, MSFT, TSLA)"),
    outputs=gr.Markdown(),
    title="Stock Sentiment Analysis",
    description="Enter a stock ticker symbol to analyze news sentiment",
    examples=[["AAPL"], ["TSLA"], ["MSFT"], ["AMZN"], ["GOOGL"]],
    allow_flagging="never"
)

# Launch the app
if __name__ == "__main__":
    iface.launch()