''' import altair as alt import numpy as np import pandas as pd import streamlit as st """ # Welcome to Streamlit! Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:. If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community forums](https://discuss.streamlit.io). In the meantime, below is an example of what you can do with just a few lines of code: """ num_points = st.slider("Number of points in spiral", 1, 10000, 1100) num_turns = st.slider("Number of turns in spiral", 1, 300, 31) indices = np.linspace(0, 1, num_points) theta = 2 * np.pi * num_turns * indices radius = indices x = radius * np.cos(theta) y = radius * np.sin(theta) df = pd.DataFrame({ "x": x, "y": y, "idx": indices, "rand": np.random.randn(num_points), }) st.altair_chart(alt.Chart(df, height=700, width=700) .mark_point(filled=True) .encode( x=alt.X("x", axis=None), y=alt.Y("y", axis=None), color=alt.Color("idx", legend=None, scale=alt.Scale()), size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])), )) import streamlit as st from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch import torch.nn.functional as F import os import pandas as pd import plotly.express as px import plotly.graph_objects as go from datetime import datetime import re # Page configuration st.set_page_config( page_title="FinBERT Sentiment Analyzer", page_icon="πŸ’°", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for better styling st.markdown(""" """, unsafe_allow_html=True) st.markdown('

πŸ’° FinBERT: Financial Sentiment Analysis

', unsafe_allow_html=True) # Sidebar with st.sidebar: st.header("ℹ️ About") st.markdown(""" **Model:** `yiyanghkust/finbert-tone` Trained specifically on financial texts for accurate sentiment analysis of: - Financial news - Earnings reports - Market analysis - Investment research """) st.header("βš™οΈ Settings") confidence_threshold = st.slider("Confidence Threshold", 0.0, 1.0, 0.5, help="Minimum confidence for sentiment classification") show_probabilities = st.checkbox("Show All Probabilities", value=True) batch_analysis = st.checkbox("Enable Batch Analysis", help="Analyze multiple texts at once") @st.cache_resource(show_spinner=False) def load_model(): """Load FinBERT model and tokenizer with error handling""" try: cache_dir = "/tmp/huggingface" os.makedirs(cache_dir, exist_ok=True) with st.spinner("Loading FinBERT model... This may take a moment."): tokenizer = AutoTokenizer.from_pretrained( "yiyanghkust/finbert-tone", cache_dir=cache_dir ) model = AutoModelForSequenceClassification.from_pretrained( "yiyanghkust/finbert-tone", cache_dir=cache_dir ) return tokenizer, model, None except Exception as e: return None, None, str(e) def analyze_sentiment(text, tokenizer, model): """Analyze sentiment with error handling and additional metrics""" try: # Preprocess text text = re.sub(r'\s+', ' ', text.strip()) inputs = tokenizer( text, return_tensors="pt", truncation=True, padding=True, max_length=512 ) with torch.no_grad(): outputs = model(**inputs) probs = F.softmax(outputs.logits, dim=1).squeeze() labels = ["Negative", "Neutral", "Positive"] sentiment_scores = {label: prob.item() for label, prob in zip(labels, probs)} # Determine primary sentiment max_prob = max(sentiment_scores.values()) primary_sentiment = max(sentiment_scores, key=sentiment_scores.get) return sentiment_scores, primary_sentiment, max_prob, None except Exception as e: return None, None, None, str(e) def create_sentiment_chart(sentiment_scores): """Create an interactive sentiment visualization""" labels = list(sentiment_scores.keys()) values = list(sentiment_scores.values()) colors = ['#f44336', '#9c27b0', '#4caf50'] fig = go.Figure(data=[ go.Bar( x=labels, y=values, marker_color=colors, text=[f'{v:.3f}' for v in values], textposition='auto', ) ]) fig.update_layout( title="Sentiment Analysis Results", xaxis_title="Sentiment", yaxis_title="Confidence Score", yaxis=dict(range=[0, 1]), height=400, showlegend=False ) return fig # Load model tokenizer, model, error = load_model() if error: st.error(f"Failed to load model: {error}") st.stop() if tokenizer and model: st.success("βœ… FinBERT model loaded successfully!") # Main analysis interface if not batch_analysis: st.header("πŸ“ Single Text Analysis") text = st.text_area( "Enter financial news, report, or analysis:", height=150, placeholder="Example: The company reported strong quarterly earnings with revenue growth of 15% year-over-year..." ) col1, col2, col3 = st.columns([1, 1, 2]) with col1: analyze_button = st.button("πŸ” Analyze Sentiment", type="primary") with col2: clear_button = st.button("πŸ—‘οΈ Clear") if clear_button: st.rerun() if analyze_button and text.strip(): with st.spinner("Analyzing sentiment..."): sentiment_scores, primary_sentiment, confidence, error = analyze_sentiment(text, tokenizer, model) if error: st.error(f"Analysis failed: {error}") else: # Results section st.header("πŸ“Š Analysis Results") # Primary sentiment with confidence col1, col2, col3 = st.columns(3) sentiment_emojis = {"Negative": "πŸ“‰", "Neutral": "😐", "Positive": "πŸ“ˆ"} sentiment_colors = {"Negative": "red", "Neutral": "gray", "Positive": "green"} with col1: st.metric( "Primary Sentiment", f"{sentiment_emojis[primary_sentiment]} {primary_sentiment}", delta=f"{confidence:.1%} confidence" ) with col2: st.metric( "Text Length", f"{len(text)} characters", delta=f"{len(text.split())} words" ) with col3: reliability = "High" if confidence > 0.7 else "Medium" if confidence > 0.5 else "Low" st.metric("Reliability", reliability) # Detailed probabilities if show_probabilities: st.subheader("Detailed Sentiment Scores") for sentiment, score in sentiment_scores.items(): emoji = sentiment_emojis[sentiment] color = "negative" if sentiment == "Negative" else "neutral" if sentiment == "Neutral" else "positive" st.markdown(f"""

{emoji} {sentiment}

{score:.3f}

""", unsafe_allow_html=True) # Visualization st.subheader("πŸ“ˆ Sentiment Visualization") fig = create_sentiment_chart(sentiment_scores) st.plotly_chart(fig, use_container_width=True) else: # Batch analysis mode st.header("πŸ“Š Batch Analysis") # Option to upload file or enter multiple texts analysis_method = st.radio( "Choose analysis method:", ["Enter multiple texts", "Upload CSV file"] ) if analysis_method == "Enter multiple texts": texts_input = st.text_area( "Enter multiple texts (one per line):", height=200, placeholder="Text 1: Company reports strong earnings...\nText 2: Market volatility increases...\nText 3: New regulations impact sector..." ) if st.button("πŸ” Analyze All Texts") and texts_input.strip(): texts = [text.strip() for text in texts_input.split('\n') if text.strip()] if texts: results = [] progress_bar = st.progress(0) for i, text in enumerate(texts): sentiment_scores, primary_sentiment, confidence, error = analyze_sentiment(text, tokenizer, model) if not error: results.append({ 'Text': text[:100] + '...' if len(text) > 100 else text, 'Primary Sentiment': primary_sentiment, 'Confidence': confidence, 'Negative': sentiment_scores['Negative'], 'Neutral': sentiment_scores['Neutral'], 'Positive': sentiment_scores['Positive'] }) progress_bar.progress((i + 1) / len(texts)) if results: df = pd.DataFrame(results) # Summary statistics st.subheader("πŸ“ˆ Batch Analysis Summary") col1, col2, col3 = st.columns(3) with col1: positive_count = len(df[df['Primary Sentiment'] == 'Positive']) st.metric("Positive Texts", positive_count, f"{positive_count/len(df)*100:.1f}%") with col2: neutral_count = len(df[df['Primary Sentiment'] == 'Neutral']) st.metric("Neutral Texts", neutral_count, f"{neutral_count/len(df)*100:.1f}%") with col3: negative_count = len(df[df['Primary Sentiment'] == 'Negative']) st.metric("Negative Texts", negative_count, f"{negative_count/len(df)*100:.1f}%") # Results table st.subheader("πŸ“‹ Detailed Results") st.dataframe(df, use_container_width=True) # Download results csv = df.to_csv(index=False) st.download_button( "πŸ“₯ Download Results (CSV)", csv, f"sentiment_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", "text/csv" ) elif analysis_method == "Upload CSV file": uploaded_file = st.file_uploader( "Choose a CSV file with a 'text' column", type=['csv'] ) if uploaded_file is not None: try: df = pd.read_csv(uploaded_file) if 'text' not in df.columns: st.error("CSV file must contain a 'text' column") else: st.write(f"Loaded {len(df)} texts from CSV file") st.dataframe(df.head(), use_container_width=True) if st.button("πŸ” Analyze CSV Data"): results = [] progress_bar = st.progress(0) for i, row in df.iterrows(): text = str(row['text']) sentiment_scores, primary_sentiment, confidence, error = analyze_sentiment(text, tokenizer, model) if not error: result_row = row.to_dict() result_row.update({ 'Primary Sentiment': primary_sentiment, 'Confidence': confidence, 'Negative Score': sentiment_scores['Negative'], 'Neutral Score': sentiment_scores['Neutral'], 'Positive Score': sentiment_scores['Positive'] }) results.append(result_row) progress_bar.progress((i + 1) / len(df)) if results: results_df = pd.DataFrame(results) # Display results st.subheader("πŸ“‹ Analysis Results") st.dataframe(results_df, use_container_width=True) # Download enhanced results csv = results_df.to_csv(index=False) st.download_button( "πŸ“₯ Download Enhanced Results (CSV)", csv, f"enhanced_sentiment_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", "text/csv" ) except Exception as e: st.error(f"Error processing CSV file: {str(e)}") # Footer st.markdown("---") st.markdown("""

πŸ’‘ Tip: For best results, use complete sentences and financial context

Built with Streamlit β€’ Powered by FinBERT

""", unsafe_allow_html=True) import streamlit as st from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch import torch.nn.functional as F import os st.set_page_config(page_title="πŸ’° FinBERT: Financial Sentiment Analysis", layout="centered") st.title("πŸ’° FinBERT: Financial Sentiment Analysis") st.markdown("МодСль: `yiyanghkust/finbert-tone` β€” ΠΎΠ±ΡƒΡ‡Π΅Π½Π° Π½Π° финансовых тСкстах") @st.cache_resource def load_model(): # Установка кастомного ΠΏΡƒΡ‚ΠΈ ΠΊ ΠΊΡΡˆΡƒ cache_dir = "/tmp/huggingface" os.makedirs(cache_dir, exist_ok=True) tokenizer = AutoTokenizer.from_pretrained("yiyanghkust/finbert-tone", cache_dir=cache_dir) model = AutoModelForSequenceClassification.from_pretrained("yiyanghkust/finbert-tone", cache_dir=cache_dir) return tokenizer, model tokenizer, model = load_model() text = st.text_area("Π’Π²Π΅Π΄ΠΈΡ‚Π΅ Ρ„ΠΈΠ½Π°Π½ΡΠΎΠ²ΡƒΡŽ Π½ΠΎΠ²ΠΎΡΡ‚ΡŒ ΠΈΠ»ΠΈ ΠΎΡ‚Ρ‡Ρ‘Ρ‚:", height=150) if st.button("ΠΠ½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ") and text.strip(): inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True) with torch.no_grad(): outputs = model(**inputs) probs = F.softmax(outputs.logits, dim=1).squeeze() labels = ["πŸ“‰ Negative", "😐 Neutral", "πŸ“ˆ Positive"] for label, prob in zip(labels, probs): st.write(f"**{label}:** {prob.item():.3f}") ''' import time import os from datetime import datetime, timedelta import re import yfinance as yf import streamlit as st from transformers import AutoTokenizer, AutoModelForSequenceClassification, AutoModelForTokenClassification, pipeline import torch import torch.nn.functional as F import pandas as pd import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots import numpy as np from textblob import TextBlob import requests from bs4 import BeautifulSoup # Page configuration st.set_page_config( page_title="Financial News Sentiment Analyzer", page_icon="πŸ“ˆ", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for financial theme st.markdown(""" """, unsafe_allow_html=True) st.markdown('

πŸ“ˆ Financial News Sentiment Analysis Platform

AI-Powered Market Intelligence & Trading Insights

', unsafe_allow_html=True) # Sidebar configuration with st.sidebar: st.header("🎯 Analysis Configuration") analysis_type = st.selectbox( "Analysis Type:", ["Single News Analysis", "Portfolio Impact Analysis", "Market Sector Analysis", "Real-time News Feed"] ) st.header("πŸ“Š Financial Models") model_choice = st.selectbox( "Sentiment Model:", ["FinBERT (Financial)", "RoBERTa (General)", "Custom Ensemble"] ) st.header("βš™οΈ Trading Parameters") risk_tolerance = st.selectbox("Risk Tolerance:", ["Conservative", "Moderate", "Aggressive"]) investment_horizon = st.selectbox("Investment Horizon:", ["Day Trading", "Swing (1-7 days)", "Position (1-3 months)", "Long-term (6+ months)"]) position_size = st.slider("Position Size ($)", 1000, 100000, 10000, 1000) st.header("πŸŽ›οΈ Alert Settings") sentiment_threshold = st.slider("Sentiment Alert Threshold", 0.0, 1.0, 0.7) enable_notifications = st.checkbox("Enable Trading Alerts") @st.cache_resource def load_financial_models(): """Load multiple financial sentiment models""" try: cache_dir = "/tmp/huggingface" os.makedirs(cache_dir, exist_ok=True) # FinBERT for financial sentiment finbert_tokenizer = AutoTokenizer.from_pretrained("yiyanghkust/finbert-tone", cache_dir=cache_dir) finbert_model = AutoModelForSequenceClassification.from_pretrained("yiyanghkust/finbert-tone", cache_dir=cache_dir) # Financial NER for entity extraction #ner_pipeline = pipeline("ner", model="elastic/distilbert-base-cased-finetuned-conll03-english", aggregation_strategy="simple", cache_dir=cache_dir) # Load Financial NER model and tokenizer explicitly ner_tokenizer = AutoTokenizer.from_pretrained( "Jean-Baptiste/roberta-large-ner-english", cache_dir=cache_dir ) ner_model = AutoModelForTokenClassification.from_pretrained( "Jean-Baptiste/roberta-large-ner-english", cache_dir=cache_dir ) # Then create pipeline using objects ner_pipeline = pipeline( "ner", model=ner_model, tokenizer=ner_tokenizer, aggregation_strategy="simple", ) return finbert_tokenizer, finbert_model, ner_pipeline, None except Exception as e: return None, None, None, str(e) def extract_financial_entities(text, ner_pipeline): """Extract companies, stocks, and financial entities from text""" try: entities = ner_pipeline(text) # Common financial terms and patterns financial_patterns = { 'stocks': r'\b([A-Z]{1,5})\b(?=\s*(?:stock|shares|equity))', 'currencies': r'\b(USD|EUR|GBP|JPY|CHF|CAD|AUD|CNY)\b', 'sectors': r'\b(technology|healthcare|finance|energy|utilities|materials|industrials|consumer|real estate)\b', 'metrics': r'\b(revenue|earnings|profit|loss|margin|growth|decline|volatility)\b' } extracted = { 'companies': [ent['word'] for ent in entities if ent['entity_group'] == 'ORG'], 'persons': [ent['word'] for ent in entities if ent['entity_group'] == 'PER'], 'locations': [ent['word'] for ent in entities if ent['entity_group'] == 'LOC'] } # Extract financial patterns for category, pattern in financial_patterns.items(): matches = re.findall(pattern, text, re.IGNORECASE) extracted[category] = matches return extracted except: return {} def analyze_financial_sentiment(text, tokenizer, model): """Comprehensive financial sentiment analysis""" try: # Basic sentiment analysis inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512) with torch.no_grad(): outputs = model(**inputs) probs = F.softmax(outputs.logits, dim=1).squeeze() sentiment_scores = { 'bearish': probs[0].item(), 'neutral': probs[1].item(), 'bullish': probs[2].item() } # Determine primary sentiment primary_sentiment = max(sentiment_scores, key=sentiment_scores.get) confidence = max(sentiment_scores.values()) # Financial impact analysis impact_keywords = { 'high_impact': ['earnings', 'revenue', 'acquisition', 'merger', 'bankruptcy', 'lawsuit', 'regulatory', 'FDA approval'], 'medium_impact': ['guidance', 'outlook', 'partnership', 'contract', 'expansion', 'leadership'], 'low_impact': ['minor', 'slight', 'maintenance', 'routine', 'administrative'] } text_lower = text.lower() impact_level = 'low' for level, keywords in impact_keywords.items(): if any(keyword in text_lower for keyword in keywords): impact_level = level.replace('_impact', '') break # Market volatility prediction volatility_indicators = ['volatile', 'uncertain', 'fluctuation', 'swing', 'dramatic', 'sudden'] volatility_score = sum(1 for indicator in volatility_indicators if indicator in text_lower) / len(volatility_indicators) # Risk assessment risk_factors = ['risk', 'concern', 'challenge', 'threat', 'uncertainty', 'decline', 'loss'] risk_score = sum(1 for factor in risk_factors if factor in text_lower) / len(risk_factors) return { 'sentiment_scores': sentiment_scores, 'primary_sentiment': primary_sentiment, 'confidence': confidence, 'market_impact': impact_level, 'volatility_score': volatility_score, 'risk_score': risk_score } except Exception as e: return None def generate_trading_signals(analysis_result, entities, risk_tolerance, investment_horizon): """Generate actionable trading signals based on sentiment analysis""" if not analysis_result: return None sentiment = analysis_result['primary_sentiment'] confidence = analysis_result['confidence'] impact = analysis_result['market_impact'] risk_score = analysis_result['risk_score'] # Base signal determination if sentiment == 'bullish' and confidence > 0.7: base_signal = 'BUY' elif sentiment == 'bearish' and confidence > 0.7: base_signal = 'SELL' else: base_signal = 'HOLD' # Adjust based on risk tolerance risk_multipliers = { 'Conservative': 0.7, 'Moderate': 1.0, 'Aggressive': 1.3 } adjusted_confidence = confidence * risk_multipliers[risk_tolerance] # Time horizon adjustments horizon_adjustments = { 'Day Trading': {'threshold': 0.8, 'hold_bias': 0.1}, 'Swing (1-7 days)': {'threshold': 0.7, 'hold_bias': 0.2}, 'Position (1-3 months)': {'threshold': 0.6, 'hold_bias': 0.3}, 'Long-term (6+ months)': {'threshold': 0.5, 'hold_bias': 0.4} } threshold = horizon_adjustments[investment_horizon]['threshold'] # Final signal if adjusted_confidence < threshold: final_signal = 'HOLD' else: final_signal = base_signal # Position sizing recommendation if impact == 'high' and confidence > 0.8: position_multiplier = 1.2 elif impact == 'low' or confidence < 0.6: position_multiplier = 0.7 else: position_multiplier = 1.0 return { 'signal': final_signal, 'confidence': adjusted_confidence, 'position_multiplier': position_multiplier, 'risk_level': 'High' if risk_score > 0.6 else 'Medium' if risk_score > 0.3 else 'Low', 'rationale': f"{sentiment.title()} sentiment ({confidence:.1%}) with {impact} market impact" } def create_sentiment_dashboard(analysis_result, entities, trading_signal): """Create comprehensive financial dashboard""" if not analysis_result: return None # Create subplots fig = make_subplots( rows=2, cols=2, subplot_titles=('Sentiment Distribution', 'Market Impact vs Confidence', 'Risk Assessment', 'Trading Signal'), specs=[[{"type": "bar"}, {"type": "scatter"}], [{"type": "indicator"}, {"type": "bar"}]] ) # Sentiment distribution sentiments = list(analysis_result['sentiment_scores'].keys()) scores = list(analysis_result['sentiment_scores'].values()) colors = ['#f44336', '#ff9800', '#4caf50'] fig.add_trace( go.Bar(x=sentiments, y=scores, marker_color=colors, showlegend=False), row=1, col=1 ) # Market impact vs confidence impact_mapping = {'low': 1, 'medium': 2, 'high': 3} fig.add_trace( go.Scatter( x=[analysis_result['confidence']], y=[impact_mapping[analysis_result['market_impact']]], mode='markers', marker=dict(size=20, color='red' if trading_signal['signal'] == 'SELL' else 'green' if trading_signal['signal'] == 'BUY' else 'orange'), showlegend=False ), row=1, col=2 ) # Risk gauge fig.add_trace( go.Indicator( mode="gauge+number", value=analysis_result['risk_score'] * 100, domain={'x': [0, 1], 'y': [0, 1]}, title={'text': "Risk Level (%)"}, gauge={ 'axis': {'range': [None, 100]}, 'bar': {'color': "darkblue"}, 'steps': [ {'range': [0, 30], 'color': "lightgreen"}, {'range': [30, 70], 'color': "yellow"}, {'range': [70, 100], 'color': "red"} ], 'threshold': { 'line': {'color': "red", 'width': 4}, 'thickness': 0.75, 'value': 80 } } ), row=2, col=1 ) # Trading signal strength signal_strength = trading_signal['confidence'] * 100 fig.add_trace( go.Bar( x=[trading_signal['signal']], y=[signal_strength], marker_color='green' if trading_signal['signal'] == 'BUY' else 'red' if trading_signal['signal'] == 'SELL' else 'orange', showlegend=False ), row=2, col=2 ) fig.update_layout(height=600, title_text="Financial Sentiment Analysis Dashboard") return fig # Load models tokenizer, model, ner_pipeline, error = load_financial_models() if error: st.error(f"Failed to load models: {error}") st.stop() if tokenizer and model: st.success("βœ… Financial AI models loaded successfully!") if analysis_type == "Single News Analysis": st.header("πŸ“° Single News Analysis") col1, col2 = st.columns([2, 1]) with col1: news_text = st.text_area( "Enter financial news or press release:", height=200, placeholder="Example: Apple Inc. reported record quarterly earnings of $123.9 billion, beating analyst expectations by 15%. The company's iPhone sales surged 25% year-over-year, driven by strong demand for the new iPhone 15 series..." ) col_a, col_b = st.columns(2) with col_a: analyze_btn = st.button("πŸ” Analyze News", type="primary") with col_b: if st.button("πŸ“Š Get Sample News"): sample_news = [ "Tesla reports record Q4 deliveries, exceeding analyst expectations by 12%. Stock surges in after-hours trading.", "Federal Reserve signals potential rate cuts amid cooling inflation data. Markets rally on dovish commentary.", "Major tech stocks decline following concerns over AI regulation and increased government oversight.", ] st.session_state.sample_news = np.random.choice(sample_news) if 'sample_news' in st.session_state: news_text = st.session_state.sample_news with col2: st.subheader("🎯 Quick Actions") if st.button("πŸ“ˆ Market Impact Simulator"): st.info("Feature available in Pro version") if st.button("πŸ“§ Setup Alert"): st.info("Alert configured successfully!") if st.button("πŸ’Ύ Save Analysis"): st.info("Analysis saved to portfolio") if analyze_btn and news_text.strip(): with st.spinner("πŸ€– Analyzing financial sentiment..."): # Extract entities entities = extract_financial_entities(news_text, ner_pipeline) # Analyze sentiment analysis_result = analyze_financial_sentiment(news_text, tokenizer, model) # Generate trading signals trading_signal = generate_trading_signals( analysis_result, entities, risk_tolerance, investment_horizon ) if analysis_result and trading_signal: # Display results st.header("πŸ“Š Financial Analysis Results") # Key metrics row col1, col2, col3, col4 = st.columns(4) with col1: sentiment_emoji = "πŸ‚" if analysis_result['primary_sentiment'] == 'bullish' else "🐻" if analysis_result['primary_sentiment'] == 'bearish' else "➑️" st.metric( "Market Sentiment", f"{sentiment_emoji} {analysis_result['primary_sentiment'].title()}", f"{analysis_result['confidence']:.1%} confidence" ) with col2: impact_emoji = "πŸ”΄" if analysis_result['market_impact'] == 'high' else "🟑" if analysis_result['market_impact'] == 'medium' else "🟒" st.metric( "Market Impact", f"{impact_emoji} {analysis_result['market_impact'].title()}", f"Risk: {trading_signal['risk_level']}" ) with col3: st.metric( "Volatility Score", f"{analysis_result['volatility_score']:.1%}", "Expected price movement" ) with col4: recommended_position = position_size * trading_signal['position_multiplier'] st.metric( "Position Size", f"${recommended_position:,.0f}", f"{(trading_signal['position_multiplier']-1)*100:+.0f}% vs base" ) # Trading signal signal_class = f"{trading_signal['signal'].lower()}-signal" st.markdown(f"""
🎯 TRADING SIGNAL: {trading_signal['signal']}
{trading_signal['rationale']}
""", unsafe_allow_html=True) # Detailed analysis col1, col2 = st.columns(2) with col1: st.subheader("πŸ“ˆ Sentiment Breakdown") for sentiment, score in analysis_result['sentiment_scores'].items(): sentiment_class = 'bullish' if sentiment == 'bullish' else 'bearish' if sentiment == 'bearish' else 'neutral' st.markdown(f"""

{'πŸ‚' if sentiment == 'bullish' else '🐻' if sentiment == 'bearish' else '➑️'} {sentiment.title()}

{score:.3f}

""", unsafe_allow_html=True) with col2: st.subheader("🏷️ Extracted Entities") if entities.get('companies'): st.write("**Companies:** " + ", ".join(entities['companies'])) if entities.get('stocks'): st.write("**Stock Symbols:** " + ", ".join(entities['stocks'])) if entities.get('sectors'): st.write("**Sectors:** " + ", ".join(entities['sectors'])) if entities.get('metrics'): st.write("**Financial Metrics:** " + ", ".join(entities['metrics'])) # Risk indicators st.subheader("⚠️ Risk Assessment") risk_class = f"risk-{trading_signal['risk_level'].lower()}" st.markdown(f'{trading_signal["risk_level"]} Risk', unsafe_allow_html=True) # Dashboard visualization st.subheader("πŸ“Š Interactive Dashboard") dashboard_fig = create_sentiment_dashboard(analysis_result, entities, trading_signal) if dashboard_fig: st.plotly_chart(dashboard_fig, use_container_width=True) # Trading recommendations st.subheader("πŸ’‘ Trading Recommendations") recommendations = [] if trading_signal['signal'] == 'BUY': recommendations.extend([ f"βœ… Consider opening a long position with {trading_signal['confidence']:.1%} confidence", f"🎯 Recommended position size: ${recommended_position:,.0f}", f"⏰ Time horizon: {investment_horizon}", "πŸ“Š Monitor for confirmation signals in next 24-48 hours" ]) elif trading_signal['signal'] == 'SELL': recommendations.extend([ f"❌ Consider reducing exposure or opening short position", f"πŸ›‘οΈ Implement stop-loss at current levels", f"⚠️ High risk scenario - monitor closely", "πŸ“‰ Consider defensive positioning" ]) else: recommendations.extend([ f"⏸️ Hold current positions - mixed signals detected", f"πŸ‘€ Wait for clearer market direction", f"πŸ“Š Monitor for breakthrough above {sentiment_threshold:.1%} confidence", "πŸ”„ Re-evaluate in 24-48 hours" ]) for rec in recommendations: st.write(rec) # Export options st.subheader("πŸ“₯ Export & Alerts") col1, col2, col3 = st.columns(3) with col1: if st.button("πŸ“Š Export Report"): report_data = { 'timestamp': datetime.now().isoformat(), 'news_text': news_text[:200] + "...", 'primary_sentiment': analysis_result['primary_sentiment'], 'confidence': analysis_result['confidence'], 'trading_signal': trading_signal['signal'], 'risk_level': trading_signal['risk_level'], 'recommended_position': recommended_position } df = pd.DataFrame([report_data]) csv = df.to_csv(index=False) st.download_button( "πŸ“₯ Download Analysis Report", csv, f"financial_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv", "text/csv" ) with col2: if st.button("πŸ”” Setup Price Alert"): st.success("Price alert configured for significant moves!") with col3: if st.button("πŸ“§ Email Report"): st.success("Report emailed to your registered address!") elif analysis_type == "Portfolio Impact Analysis": st.header("πŸ’Ό Portfolio Impact Analysis") st.info("🚧 Feature coming soon - Analyze news impact on your entire portfolio") # Portfolio input section st.subheader("πŸ“Š Your Portfolio") portfolio_input = st.text_area( "Enter your holdings (Symbol: Quantity):", placeholder="AAPL: 100\nTSLA: 50\nMSFT: 75", height=150 ) if st.button("πŸ“ˆ Analyze Portfolio Impact"): st.success("Portfolio analysis feature will be available in the next update!") elif analysis_type == "Market Sector Analysis": st.header("🏭 Market Sector Analysis") st.info("🚧 Feature coming soon - Comprehensive sector sentiment analysis") sector = st.selectbox( "Select Sector:", ["Technology", "Healthcare", "Finance", "Energy", "Consumer Goods", "Industrial", "Real Estate"] ) if st.button("πŸ” Analyze Sector"): st.success("Sector analysis feature will be available in the next update!") else: # Real-time News Feed st.header("πŸ“‘ Real-time News Feed Analysis") st.info("🚧 Feature coming soon - Live news sentiment monitoring") if st.button("πŸ”„ Start Live Monitoring"): st.success("Live monitoring feature will be available in the next update!") # Footer st.markdown("---") st.markdown("""

⚠️ Disclaimer: This analysis is for informational purposes only and should not be considered as financial advice.

Always consult with a qualified financial advisor before making investment decisions.

πŸ€– Powered by Advanced AI β€’ Built for Professional Traders & Investors

""", unsafe_allow_html=True)