ResearchEngineering commited on
Commit
7c59760
Β·
verified Β·
1 Parent(s): 0383b05

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +601 -1
src/streamlit_app.py CHANGED
@@ -405,7 +405,9 @@ st.markdown("""
405
  </div>
406
  """, unsafe_allow_html=True)
407
 
408
- '''
 
 
409
 
410
 
411
 
@@ -443,3 +445,601 @@ if st.button("ΠΠ½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ") and text.strip
443
  for label, prob in zip(labels, probs):
444
  st.write(f"**{label}:** {prob.item():.3f}")
445
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  </div>
406
  """, unsafe_allow_html=True)
407
 
408
+
409
+
410
+
411
 
412
 
413
 
 
445
  for label, prob in zip(labels, probs):
446
  st.write(f"**{label}:** {prob.item():.3f}")
447
 
448
+ '''
449
+
450
+ import streamlit as st
451
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
452
+ import torch
453
+ import torch.nn.functional as F
454
+ import pandas as pd
455
+ import plotly.express as px
456
+ import plotly.graph_objects as go
457
+ from plotly.subplots import make_subplots
458
+ import numpy as np
459
+ from datetime import datetime, timedelta
460
+ import re
461
+ import yfinance as yf
462
+ from textblob import TextBlob
463
+ import requests
464
+ from bs4 import BeautifulSoup
465
+ import time
466
+
467
+ # Page configuration
468
+ st.set_page_config(
469
+ page_title="Financial News Sentiment Analyzer",
470
+ page_icon="πŸ“ˆ",
471
+ layout="wide",
472
+ initial_sidebar_state="expanded"
473
+ )
474
+
475
+ # Custom CSS for financial theme
476
+ st.markdown("""
477
+ <style>
478
+ .main-header {
479
+ text-align: center;
480
+ background: linear-gradient(90deg, #1f4e79, #2e7d32);
481
+ color: white;
482
+ padding: 1rem;
483
+ border-radius: 15px;
484
+ margin-bottom: 2rem;
485
+ }
486
+ .metric-card {
487
+ background: white;
488
+ padding: 1.5rem;
489
+ border-radius: 10px;
490
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
491
+ border-left: 4px solid #1f4e79;
492
+ margin: 1rem 0;
493
+ }
494
+ .bullish { border-left-color: #4caf50 !important; }
495
+ .bearish { border-left-color: #f44336 !important; }
496
+ .neutral { border-left-color: #ff9800 !important; }
497
+ .market-impact {
498
+ padding: 1rem;
499
+ border-radius: 8px;
500
+ margin: 0.5rem 0;
501
+ font-weight: bold;
502
+ }
503
+ .high-impact { background-color: #ffebee; color: #c62828; }
504
+ .medium-impact { background-color: #fff3e0; color: #ef6c00; }
505
+ .low-impact { background-color: #e8f5e8; color: #2e7d32; }
506
+ .trading-signal {
507
+ padding: 1rem;
508
+ border-radius: 10px;
509
+ text-align: center;
510
+ font-size: 1.2rem;
511
+ font-weight: bold;
512
+ margin: 1rem 0;
513
+ }
514
+ .buy-signal { background: linear-gradient(135deg, #4caf50, #66bb6a); color: white; }
515
+ .sell-signal { background: linear-gradient(135deg, #f44336, #ef5350); color: white; }
516
+ .hold-signal { background: linear-gradient(135deg, #ff9800, #ffa726); color: white; }
517
+ .risk-indicator {
518
+ display: inline-block;
519
+ padding: 0.3rem 0.8rem;
520
+ border-radius: 20px;
521
+ font-size: 0.9rem;
522
+ font-weight: bold;
523
+ margin: 0.2rem;
524
+ }
525
+ .risk-low { background-color: #4caf50; color: white; }
526
+ .risk-medium { background-color: #ff9800; color: white; }
527
+ .risk-high { background-color: #f44336; color: white; }
528
+ </style>
529
+ """, unsafe_allow_html=True)
530
+
531
+ st.markdown('<div class="main-header"><h1>πŸ“ˆ Financial News Sentiment Analysis Platform</h1><p>AI-Powered Market Intelligence & Trading Insights</p></div>', unsafe_allow_html=True)
532
+
533
+ # Sidebar configuration
534
+ with st.sidebar:
535
+ st.header("🎯 Analysis Configuration")
536
+
537
+ analysis_type = st.selectbox(
538
+ "Analysis Type:",
539
+ ["Single News Analysis", "Portfolio Impact Analysis", "Market Sector Analysis", "Real-time News Feed"]
540
+ )
541
+
542
+ st.header("πŸ“Š Financial Models")
543
+ model_choice = st.selectbox(
544
+ "Sentiment Model:",
545
+ ["FinBERT (Financial)", "RoBERTa (General)", "Custom Ensemble"]
546
+ )
547
+
548
+ st.header("βš™οΈ Trading Parameters")
549
+ risk_tolerance = st.selectbox("Risk Tolerance:", ["Conservative", "Moderate", "Aggressive"])
550
+ investment_horizon = st.selectbox("Investment Horizon:", ["Day Trading", "Swing (1-7 days)", "Position (1-3 months)", "Long-term (6+ months)"])
551
+ position_size = st.slider("Position Size ($)", 1000, 100000, 10000, 1000)
552
+
553
+ st.header("πŸŽ›οΈ Alert Settings")
554
+ sentiment_threshold = st.slider("Sentiment Alert Threshold", 0.0, 1.0, 0.7)
555
+ enable_notifications = st.checkbox("Enable Trading Alerts")
556
+
557
+ @st.cache_resource
558
+ def load_financial_models():
559
+ """Load multiple financial sentiment models"""
560
+ try:
561
+ # FinBERT for financial sentiment
562
+ finbert_tokenizer = AutoTokenizer.from_pretrained("yiyanghkust/finbert-tone")
563
+ finbert_model = AutoModelForSequenceClassification.from_pretrained("yiyanghkust/finbert-tone")
564
+
565
+ # Financial NER for entity extraction
566
+ ner_pipeline = pipeline("ner", model="dbmdz/bert-large-cased-finetuned-conll03-english", aggregation_strategy="simple")
567
+
568
+ return finbert_tokenizer, finbert_model, ner_pipeline, None
569
+ except Exception as e:
570
+ return None, None, None, str(e)
571
+
572
+ def extract_financial_entities(text, ner_pipeline):
573
+ """Extract companies, stocks, and financial entities from text"""
574
+ try:
575
+ entities = ner_pipeline(text)
576
+
577
+ # Common financial terms and patterns
578
+ financial_patterns = {
579
+ 'stocks': r'\b([A-Z]{1,5})\b(?=\s*(?:stock|shares|equity))',
580
+ 'currencies': r'\b(USD|EUR|GBP|JPY|CHF|CAD|AUD|CNY)\b',
581
+ 'sectors': r'\b(technology|healthcare|finance|energy|utilities|materials|industrials|consumer|real estate)\b',
582
+ 'metrics': r'\b(revenue|earnings|profit|loss|margin|growth|decline|volatility)\b'
583
+ }
584
+
585
+ extracted = {
586
+ 'companies': [ent['word'] for ent in entities if ent['entity_group'] == 'ORG'],
587
+ 'persons': [ent['word'] for ent in entities if ent['entity_group'] == 'PER'],
588
+ 'locations': [ent['word'] for ent in entities if ent['entity_group'] == 'LOC']
589
+ }
590
+
591
+ # Extract financial patterns
592
+ for category, pattern in financial_patterns.items():
593
+ matches = re.findall(pattern, text, re.IGNORECASE)
594
+ extracted[category] = matches
595
+
596
+ return extracted
597
+ except:
598
+ return {}
599
+
600
+ def analyze_financial_sentiment(text, tokenizer, model):
601
+ """Comprehensive financial sentiment analysis"""
602
+ try:
603
+ # Basic sentiment analysis
604
+ inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512)
605
+
606
+ with torch.no_grad():
607
+ outputs = model(**inputs)
608
+ probs = F.softmax(outputs.logits, dim=1).squeeze()
609
+
610
+ sentiment_scores = {
611
+ 'bearish': probs[0].item(),
612
+ 'neutral': probs[1].item(),
613
+ 'bullish': probs[2].item()
614
+ }
615
+
616
+ # Determine primary sentiment
617
+ primary_sentiment = max(sentiment_scores, key=sentiment_scores.get)
618
+ confidence = max(sentiment_scores.values())
619
+
620
+ # Financial impact analysis
621
+ impact_keywords = {
622
+ 'high_impact': ['earnings', 'revenue', 'acquisition', 'merger', 'bankruptcy', 'lawsuit', 'regulatory', 'FDA approval'],
623
+ 'medium_impact': ['guidance', 'outlook', 'partnership', 'contract', 'expansion', 'leadership'],
624
+ 'low_impact': ['minor', 'slight', 'maintenance', 'routine', 'administrative']
625
+ }
626
+
627
+ text_lower = text.lower()
628
+ impact_level = 'low'
629
+
630
+ for level, keywords in impact_keywords.items():
631
+ if any(keyword in text_lower for keyword in keywords):
632
+ impact_level = level.replace('_impact', '')
633
+ break
634
+
635
+ # Market volatility prediction
636
+ volatility_indicators = ['volatile', 'uncertain', 'fluctuation', 'swing', 'dramatic', 'sudden']
637
+ volatility_score = sum(1 for indicator in volatility_indicators if indicator in text_lower) / len(volatility_indicators)
638
+
639
+ # Risk assessment
640
+ risk_factors = ['risk', 'concern', 'challenge', 'threat', 'uncertainty', 'decline', 'loss']
641
+ risk_score = sum(1 for factor in risk_factors if factor in text_lower) / len(risk_factors)
642
+
643
+ return {
644
+ 'sentiment_scores': sentiment_scores,
645
+ 'primary_sentiment': primary_sentiment,
646
+ 'confidence': confidence,
647
+ 'market_impact': impact_level,
648
+ 'volatility_score': volatility_score,
649
+ 'risk_score': risk_score
650
+ }
651
+
652
+ except Exception as e:
653
+ return None
654
+
655
+ def generate_trading_signals(analysis_result, entities, risk_tolerance, investment_horizon):
656
+ """Generate actionable trading signals based on sentiment analysis"""
657
+
658
+ if not analysis_result:
659
+ return None
660
+
661
+ sentiment = analysis_result['primary_sentiment']
662
+ confidence = analysis_result['confidence']
663
+ impact = analysis_result['market_impact']
664
+ risk_score = analysis_result['risk_score']
665
+
666
+ # Base signal determination
667
+ if sentiment == 'bullish' and confidence > 0.7:
668
+ base_signal = 'BUY'
669
+ elif sentiment == 'bearish' and confidence > 0.7:
670
+ base_signal = 'SELL'
671
+ else:
672
+ base_signal = 'HOLD'
673
+
674
+ # Adjust based on risk tolerance
675
+ risk_multipliers = {
676
+ 'Conservative': 0.7,
677
+ 'Moderate': 1.0,
678
+ 'Aggressive': 1.3
679
+ }
680
+
681
+ adjusted_confidence = confidence * risk_multipliers[risk_tolerance]
682
+
683
+ # Time horizon adjustments
684
+ horizon_adjustments = {
685
+ 'Day Trading': {'threshold': 0.8, 'hold_bias': 0.1},
686
+ 'Swing (1-7 days)': {'threshold': 0.7, 'hold_bias': 0.2},
687
+ 'Position (1-3 months)': {'threshold': 0.6, 'hold_bias': 0.3},
688
+ 'Long-term (6+ months)': {'threshold': 0.5, 'hold_bias': 0.4}
689
+ }
690
+
691
+ threshold = horizon_adjustments[investment_horizon]['threshold']
692
+
693
+ # Final signal
694
+ if adjusted_confidence < threshold:
695
+ final_signal = 'HOLD'
696
+ else:
697
+ final_signal = base_signal
698
+
699
+ # Position sizing recommendation
700
+ if impact == 'high' and confidence > 0.8:
701
+ position_multiplier = 1.2
702
+ elif impact == 'low' or confidence < 0.6:
703
+ position_multiplier = 0.7
704
+ else:
705
+ position_multiplier = 1.0
706
+
707
+ return {
708
+ 'signal': final_signal,
709
+ 'confidence': adjusted_confidence,
710
+ 'position_multiplier': position_multiplier,
711
+ 'risk_level': 'High' if risk_score > 0.6 else 'Medium' if risk_score > 0.3 else 'Low',
712
+ 'rationale': f"{sentiment.title()} sentiment ({confidence:.1%}) with {impact} market impact"
713
+ }
714
+
715
+ def create_sentiment_dashboard(analysis_result, entities, trading_signal):
716
+ """Create comprehensive financial dashboard"""
717
+
718
+ if not analysis_result:
719
+ return None
720
+
721
+ # Create subplots
722
+ fig = make_subplots(
723
+ rows=2, cols=2,
724
+ subplot_titles=('Sentiment Distribution', 'Market Impact vs Confidence', 'Risk Assessment', 'Trading Signal'),
725
+ specs=[[{"type": "bar"}, {"type": "scatter"}],
726
+ [{"type": "indicator"}, {"type": "bar"}]]
727
+ )
728
+
729
+ # Sentiment distribution
730
+ sentiments = list(analysis_result['sentiment_scores'].keys())
731
+ scores = list(analysis_result['sentiment_scores'].values())
732
+ colors = ['#f44336', '#ff9800', '#4caf50']
733
+
734
+ fig.add_trace(
735
+ go.Bar(x=sentiments, y=scores, marker_color=colors, showlegend=False),
736
+ row=1, col=1
737
+ )
738
+
739
+ # Market impact vs confidence
740
+ impact_mapping = {'low': 1, 'medium': 2, 'high': 3}
741
+ fig.add_trace(
742
+ go.Scatter(
743
+ x=[analysis_result['confidence']],
744
+ y=[impact_mapping[analysis_result['market_impact']]],
745
+ mode='markers',
746
+ marker=dict(size=20, color='red' if trading_signal['signal'] == 'SELL' else 'green' if trading_signal['signal'] == 'BUY' else 'orange'),
747
+ showlegend=False
748
+ ),
749
+ row=1, col=2
750
+ )
751
+
752
+ # Risk gauge
753
+ fig.add_trace(
754
+ go.Indicator(
755
+ mode="gauge+number",
756
+ value=analysis_result['risk_score'] * 100,
757
+ domain={'x': [0, 1], 'y': [0, 1]},
758
+ title={'text': "Risk Level (%)"},
759
+ gauge={
760
+ 'axis': {'range': [None, 100]},
761
+ 'bar': {'color': "darkblue"},
762
+ 'steps': [
763
+ {'range': [0, 30], 'color': "lightgreen"},
764
+ {'range': [30, 70], 'color': "yellow"},
765
+ {'range': [70, 100], 'color': "red"}
766
+ ],
767
+ 'threshold': {
768
+ 'line': {'color': "red", 'width': 4},
769
+ 'thickness': 0.75,
770
+ 'value': 80
771
+ }
772
+ }
773
+ ),
774
+ row=2, col=1
775
+ )
776
+
777
+ # Trading signal strength
778
+ signal_strength = trading_signal['confidence'] * 100
779
+ fig.add_trace(
780
+ go.Bar(
781
+ x=[trading_signal['signal']],
782
+ y=[signal_strength],
783
+ marker_color='green' if trading_signal['signal'] == 'BUY' else 'red' if trading_signal['signal'] == 'SELL' else 'orange',
784
+ showlegend=False
785
+ ),
786
+ row=2, col=2
787
+ )
788
+
789
+ fig.update_layout(height=600, title_text="Financial Sentiment Analysis Dashboard")
790
+ return fig
791
+
792
+ # Load models
793
+ tokenizer, model, ner_pipeline, error = load_financial_models()
794
+
795
+ if error:
796
+ st.error(f"Failed to load models: {error}")
797
+ st.stop()
798
+
799
+ if tokenizer and model:
800
+ st.success("βœ… Financial AI models loaded successfully!")
801
+
802
+ if analysis_type == "Single News Analysis":
803
+ st.header("πŸ“° Single News Analysis")
804
+
805
+ col1, col2 = st.columns([2, 1])
806
+
807
+ with col1:
808
+ news_text = st.text_area(
809
+ "Enter financial news or press release:",
810
+ height=200,
811
+ 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..."
812
+ )
813
+
814
+ col_a, col_b = st.columns(2)
815
+ with col_a:
816
+ analyze_btn = st.button("πŸ” Analyze News", type="primary")
817
+ with col_b:
818
+ if st.button("πŸ“Š Get Sample News"):
819
+ sample_news = [
820
+ "Tesla reports record Q4 deliveries, exceeding analyst expectations by 12%. Stock surges in after-hours trading.",
821
+ "Federal Reserve signals potential rate cuts amid cooling inflation data. Markets rally on dovish commentary.",
822
+ "Major tech stocks decline following concerns over AI regulation and increased government oversight.",
823
+ ]
824
+ st.session_state.sample_news = np.random.choice(sample_news)
825
+
826
+ if 'sample_news' in st.session_state:
827
+ news_text = st.session_state.sample_news
828
+
829
+ with col2:
830
+ st.subheader("🎯 Quick Actions")
831
+ if st.button("πŸ“ˆ Market Impact Simulator"):
832
+ st.info("Feature available in Pro version")
833
+ if st.button("πŸ“§ Setup Alert"):
834
+ st.info("Alert configured successfully!")
835
+ if st.button("πŸ’Ύ Save Analysis"):
836
+ st.info("Analysis saved to portfolio")
837
+
838
+ if analyze_btn and news_text.strip():
839
+ with st.spinner("πŸ€– Analyzing financial sentiment..."):
840
+ # Extract entities
841
+ entities = extract_financial_entities(news_text, ner_pipeline)
842
+
843
+ # Analyze sentiment
844
+ analysis_result = analyze_financial_sentiment(news_text, tokenizer, model)
845
+
846
+ # Generate trading signals
847
+ trading_signal = generate_trading_signals(
848
+ analysis_result, entities, risk_tolerance, investment_horizon
849
+ )
850
+
851
+ if analysis_result and trading_signal:
852
+ # Display results
853
+ st.header("πŸ“Š Financial Analysis Results")
854
+
855
+ # Key metrics row
856
+ col1, col2, col3, col4 = st.columns(4)
857
+
858
+ with col1:
859
+ sentiment_emoji = "πŸ‚" if analysis_result['primary_sentiment'] == 'bullish' else "🐻" if analysis_result['primary_sentiment'] == 'bearish' else "➑️"
860
+ st.metric(
861
+ "Market Sentiment",
862
+ f"{sentiment_emoji} {analysis_result['primary_sentiment'].title()}",
863
+ f"{analysis_result['confidence']:.1%} confidence"
864
+ )
865
+
866
+ with col2:
867
+ impact_emoji = "πŸ”΄" if analysis_result['market_impact'] == 'high' else "🟑" if analysis_result['market_impact'] == 'medium' else "🟒"
868
+ st.metric(
869
+ "Market Impact",
870
+ f"{impact_emoji} {analysis_result['market_impact'].title()}",
871
+ f"Risk: {trading_signal['risk_level']}"
872
+ )
873
+
874
+ with col3:
875
+ st.metric(
876
+ "Volatility Score",
877
+ f"{analysis_result['volatility_score']:.1%}",
878
+ "Expected price movement"
879
+ )
880
+
881
+ with col4:
882
+ recommended_position = position_size * trading_signal['position_multiplier']
883
+ st.metric(
884
+ "Position Size",
885
+ f"${recommended_position:,.0f}",
886
+ f"{(trading_signal['position_multiplier']-1)*100:+.0f}% vs base"
887
+ )
888
+
889
+ # Trading signal
890
+ signal_class = f"{trading_signal['signal'].lower()}-signal"
891
+ st.markdown(f"""
892
+ <div class="trading-signal {signal_class}">
893
+ 🎯 TRADING SIGNAL: {trading_signal['signal']}
894
+ <br><small>{trading_signal['rationale']}</small>
895
+ </div>
896
+ """, unsafe_allow_html=True)
897
+
898
+ # Detailed analysis
899
+ col1, col2 = st.columns(2)
900
+
901
+ with col1:
902
+ st.subheader("πŸ“ˆ Sentiment Breakdown")
903
+ for sentiment, score in analysis_result['sentiment_scores'].items():
904
+ sentiment_class = 'bullish' if sentiment == 'bullish' else 'bearish' if sentiment == 'bearish' else 'neutral'
905
+ st.markdown(f"""
906
+ <div class="metric-card {sentiment_class}">
907
+ <h4>{'πŸ‚' if sentiment == 'bullish' else '🐻' if sentiment == 'bearish' else '➑️'} {sentiment.title()}</h4>
908
+ <h2>{score:.3f}</h2>
909
+ <div style="width: 100%; background-color: #ddd; border-radius: 25px; height: 10px;">
910
+ <div style="width: {score*100}%; height: 10px; background-color: {'#4caf50' if sentiment == 'bullish' else '#f44336' if sentiment == 'bearish' else '#ff9800'}; border-radius: 25px;"></div>
911
+ </div>
912
+ </div>
913
+ """, unsafe_allow_html=True)
914
+
915
+ with col2:
916
+ st.subheader("🏷️ Extracted Entities")
917
+
918
+ if entities.get('companies'):
919
+ st.write("**Companies:** " + ", ".join(entities['companies']))
920
+ if entities.get('stocks'):
921
+ st.write("**Stock Symbols:** " + ", ".join(entities['stocks']))
922
+ if entities.get('sectors'):
923
+ st.write("**Sectors:** " + ", ".join(entities['sectors']))
924
+ if entities.get('metrics'):
925
+ st.write("**Financial Metrics:** " + ", ".join(entities['metrics']))
926
+
927
+ # Risk indicators
928
+ st.subheader("⚠️ Risk Assessment")
929
+ risk_class = f"risk-{trading_signal['risk_level'].lower()}"
930
+ st.markdown(f'<span class="risk-indicator {risk_class}">{trading_signal["risk_level"]} Risk</span>', unsafe_allow_html=True)
931
+
932
+ # Dashboard visualization
933
+ st.subheader("πŸ“Š Interactive Dashboard")
934
+ dashboard_fig = create_sentiment_dashboard(analysis_result, entities, trading_signal)
935
+ if dashboard_fig:
936
+ st.plotly_chart(dashboard_fig, use_container_width=True)
937
+
938
+ # Trading recommendations
939
+ st.subheader("πŸ’‘ Trading Recommendations")
940
+
941
+ recommendations = []
942
+
943
+ if trading_signal['signal'] == 'BUY':
944
+ recommendations.extend([
945
+ f"βœ… Consider opening a long position with {trading_signal['confidence']:.1%} confidence",
946
+ f"🎯 Recommended position size: ${recommended_position:,.0f}",
947
+ f"⏰ Time horizon: {investment_horizon}",
948
+ "πŸ“Š Monitor for confirmation signals in next 24-48 hours"
949
+ ])
950
+ elif trading_signal['signal'] == 'SELL':
951
+ recommendations.extend([
952
+ f"❌ Consider reducing exposure or opening short position",
953
+ f"πŸ›‘οΈ Implement stop-loss at current levels",
954
+ f"⚠️ High risk scenario - monitor closely",
955
+ "πŸ“‰ Consider defensive positioning"
956
+ ])
957
+ else:
958
+ recommendations.extend([
959
+ f"⏸️ Hold current positions - mixed signals detected",
960
+ f"πŸ‘€ Wait for clearer market direction",
961
+ f"πŸ“Š Monitor for breakthrough above {sentiment_threshold:.1%} confidence",
962
+ "πŸ”„ Re-evaluate in 24-48 hours"
963
+ ])
964
+
965
+ for rec in recommendations:
966
+ st.write(rec)
967
+
968
+ # Export options
969
+ st.subheader("πŸ“₯ Export & Alerts")
970
+ col1, col2, col3 = st.columns(3)
971
+
972
+ with col1:
973
+ if st.button("πŸ“Š Export Report"):
974
+ report_data = {
975
+ 'timestamp': datetime.now().isoformat(),
976
+ 'news_text': news_text[:200] + "...",
977
+ 'primary_sentiment': analysis_result['primary_sentiment'],
978
+ 'confidence': analysis_result['confidence'],
979
+ 'trading_signal': trading_signal['signal'],
980
+ 'risk_level': trading_signal['risk_level'],
981
+ 'recommended_position': recommended_position
982
+ }
983
+
984
+ df = pd.DataFrame([report_data])
985
+ csv = df.to_csv(index=False)
986
+ st.download_button(
987
+ "πŸ“₯ Download Analysis Report",
988
+ csv,
989
+ f"financial_analysis_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
990
+ "text/csv"
991
+ )
992
+
993
+ with col2:
994
+ if st.button("πŸ”” Setup Price Alert"):
995
+ st.success("Price alert configured for significant moves!")
996
+
997
+ with col3:
998
+ if st.button("πŸ“§ Email Report"):
999
+ st.success("Report emailed to your registered address!")
1000
+
1001
+ elif analysis_type == "Portfolio Impact Analysis":
1002
+ st.header("πŸ’Ό Portfolio Impact Analysis")
1003
+ st.info("🚧 Feature coming soon - Analyze news impact on your entire portfolio")
1004
+
1005
+ # Portfolio input section
1006
+ st.subheader("πŸ“Š Your Portfolio")
1007
+ portfolio_input = st.text_area(
1008
+ "Enter your holdings (Symbol: Quantity):",
1009
+ placeholder="AAPL: 100\nTSLA: 50\nMSFT: 75",
1010
+ height=150
1011
+ )
1012
+
1013
+ if st.button("πŸ“ˆ Analyze Portfolio Impact"):
1014
+ st.success("Portfolio analysis feature will be available in the next update!")
1015
+
1016
+ elif analysis_type == "Market Sector Analysis":
1017
+ st.header("🏭 Market Sector Analysis")
1018
+ st.info("🚧 Feature coming soon - Comprehensive sector sentiment analysis")
1019
+
1020
+ sector = st.selectbox(
1021
+ "Select Sector:",
1022
+ ["Technology", "Healthcare", "Finance", "Energy", "Consumer Goods", "Industrial", "Real Estate"]
1023
+ )
1024
+
1025
+ if st.button("πŸ” Analyze Sector"):
1026
+ st.success("Sector analysis feature will be available in the next update!")
1027
+
1028
+ else: # Real-time News Feed
1029
+ st.header("πŸ“‘ Real-time News Feed Analysis")
1030
+ st.info("🚧 Feature coming soon - Live news sentiment monitoring")
1031
+
1032
+ if st.button("πŸ”„ Start Live Monitoring"):
1033
+ st.success("Live monitoring feature will be available in the next update!")
1034
+
1035
+ # Footer
1036
+ st.markdown("---")
1037
+ st.markdown("""
1038
+ <div style='text-align: center; color: #666; margin-top: 2rem;'>
1039
+ <p><strong>⚠️ Disclaimer:</strong> This analysis is for informational purposes only and should not be considered as financial advice.</p>
1040
+ <p>Always consult with a qualified financial advisor before making investment decisions.</p>
1041
+ <p>πŸ€– Powered by Advanced AI β€’ Built for Professional Traders & Investors</p>
1042
+ </div>
1043
+ """, unsafe_allow_html=True)
1044
+
1045
+