Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Advanced Stock Analysis</title> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
| <style> | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background-color: #f8f9fa; | |
| } | |
| .analysis-card { | |
| background-color: white; | |
| border-radius: 10px; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |
| margin-bottom: 20px; | |
| overflow: hidden; | |
| } | |
| .analysis-header { | |
| background-color: #2c3e50; | |
| color: white; | |
| padding: 15px; | |
| font-weight: 600; | |
| } | |
| .analysis-body { | |
| padding: 20px; | |
| } | |
| .chart-container { | |
| height: 400px; | |
| margin: 20px 0; | |
| } | |
| .indicator-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
| gap: 15px; | |
| margin-top: 15px; | |
| } | |
| .indicator-card { | |
| background-color: #f8f9fa; | |
| padding: 15px; | |
| border-radius: 8px; | |
| } | |
| .indicator-value { | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| } | |
| .signal { | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| font-size: 0.9rem; | |
| } | |
| .signal-bullish { background-color: #d4edda; color: #155724; } | |
| .signal-bearish { background-color: #f8d7da; color: #721c24; } | |
| .signal-neutral { background-color: #e2e3e5; color: #383d41; } | |
| </style> | |
| </head> | |
| <body> | |
| <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> | |
| <div class="container"> | |
| <a class="navbar-brand" href="/"> | |
| <i class="fas fa-chart-line me-2"></i>Stock Analysis | |
| </a> | |
| <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> | |
| <span class="navbar-toggler-icon"></span> | |
| </button> | |
| <div class="collapse navbar-collapse" id="navbarNav"> | |
| <ul class="navbar-nav ms-auto"> | |
| <li class="nav-item"> | |
| <a class="nav-link" href="/">Home</a> | |
| </li> | |
| <li class="nav-item"> | |
| <a class="nav-link" href="/dashboard">Dashboard</a> | |
| </li> | |
| <li class="nav-item"> | |
| <a class="nav-link active" href="/advanced">Advanced Analysis</a> | |
| </li> | |
| </ul> | |
| </div> | |
| </div> | |
| </nav> | |
| <div class="container mt-4"> | |
| <div class="row mb-4"> | |
| <div class="col"> | |
| <div class="input-group"> | |
| <input type="text" id="stockInput" class="form-control" placeholder="Enter stock ticker (e.g., AAPL)"> | |
| <button class="btn btn-primary" onclick="analyzeStock()"> | |
| <i class="fas fa-search me-2"></i>Analyze | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="analysisContent" style="display: none;"> | |
| <div class="row"> | |
| <!-- Price Chart --> | |
| <div class="col-12"> | |
| <div class="analysis-card"> | |
| <div class="analysis-header"> | |
| <i class="fas fa-chart-line me-2"></i>Price Analysis | |
| </div> | |
| <div class="analysis-body"> | |
| <div class="chart-container"> | |
| <canvas id="priceChart"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Technical Indicators --> | |
| <div class="col-md-6"> | |
| <div class="analysis-card"> | |
| <div class="analysis-header"> | |
| <i class="fas fa-calculator me-2"></i>Technical Indicators | |
| </div> | |
| <div class="analysis-body"> | |
| <div id="technicalIndicators" class="indicator-grid"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Pattern Analysis --> | |
| <div class="col-md-6"> | |
| <div class="analysis-card"> | |
| <div class="analysis-header"> | |
| <i class="fas fa-shapes me-2"></i>Pattern Analysis | |
| </div> | |
| <div class="analysis-body"> | |
| <div id="patternAnalysis"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Volume Analysis --> | |
| <div class="col-md-6"> | |
| <div class="analysis-card"> | |
| <div class="analysis-header"> | |
| <i class="fas fa-chart-bar me-2"></i>Volume Analysis | |
| </div> | |
| <div class="analysis-body"> | |
| <div class="chart-container"> | |
| <canvas id="volumeChart"></canvas> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Sentiment Analysis --> | |
| <div class="col-md-6"> | |
| <div class="analysis-card"> | |
| <div class="analysis-header"> | |
| <i class="fas fa-comments me-2"></i>Market Sentiment | |
| </div> | |
| <div class="analysis-body"> | |
| <div id="sentimentAnalysis"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> | |
| <script> | |
| let priceChart = null; | |
| let volumeChart = null; | |
| function analyzeStock() { | |
| const ticker = document.getElementById('stockInput').value.toUpperCase(); | |
| if (!ticker) return; | |
| document.getElementById('analysisContent').style.display = 'block'; | |
| // Fetch stock details | |
| fetch(`/api/stock/${ticker}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| updatePriceChart(data.data); | |
| updateTechnicalIndicators(data.data.technical_analysis); | |
| } | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| // Fetch pattern analysis | |
| fetch(`/api/pattern_analysis/${ticker}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| updatePatternAnalysis(data.data); | |
| } | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| // Fetch sentiment analysis | |
| fetch(`/api/sentiment_analysis/${ticker}`) | |
| .then(response => response.json()) | |
| .then(data => { | |
| if (data.status === 'success') { | |
| updateSentimentAnalysis(data.data); | |
| } | |
| }) | |
| .catch(error => console.error('Error:', error)); | |
| } | |
| function updatePriceChart(data) { | |
| const ctx = document.getElementById('priceChart').getContext('2d'); | |
| if (priceChart) { | |
| priceChart.destroy(); | |
| } | |
| priceChart = new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: data.chartData.dates, | |
| datasets: [ | |
| { | |
| label: 'Price', | |
| data: data.chartData.prices, | |
| borderColor: '#2ecc71', | |
| fill: false | |
| }, | |
| { | |
| label: 'SMA 20', | |
| data: data.chartData.technical_indicators.sma_20, | |
| borderColor: '#3498db', | |
| borderWidth: 1, | |
| fill: false | |
| }, | |
| { | |
| label: 'SMA 50', | |
| data: data.chartData.technical_indicators.sma_50, | |
| borderColor: '#f1c40f', | |
| borderWidth: 1, | |
| fill: false | |
| } | |
| ] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| interaction: { | |
| intersect: false, | |
| mode: 'index' | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: false | |
| } | |
| } | |
| } | |
| }); | |
| // Update volume chart | |
| const volumeCtx = document.getElementById('volumeChart').getContext('2d'); | |
| if (volumeChart) { | |
| volumeChart.destroy(); | |
| } | |
| volumeChart = new Chart(volumeCtx, { | |
| type: 'bar', | |
| data: { | |
| labels: data.chartData.dates, | |
| datasets: [{ | |
| label: 'Volume', | |
| data: data.chartData.volume, | |
| backgroundColor: '#3498db' | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false | |
| } | |
| }); | |
| } | |
| function updateTechnicalIndicators(analysis) { | |
| const container = document.getElementById('technicalIndicators'); | |
| container.innerHTML = ''; | |
| // RSI | |
| const rsiSignal = analysis.indicators.RSI.signal.toLowerCase(); | |
| container.innerHTML += ` | |
| <div class="indicator-card"> | |
| <h5>RSI (14)</h5> | |
| <div class="indicator-value">${analysis.indicators.RSI.value}</div> | |
| <span class="signal signal-${rsiSignal}">${analysis.indicators.RSI.signal}</span> | |
| </div> | |
| `; | |
| // MACD | |
| const macdSignal = analysis.indicators.MACD.signal.toLowerCase(); | |
| container.innerHTML += ` | |
| <div class="indicator-card"> | |
| <h5>MACD</h5> | |
| <div class="indicator-value">${analysis.indicators.MACD.value}</div> | |
| <span class="signal signal-${macdSignal}">${analysis.indicators.MACD.signal}</span> | |
| </div> | |
| `; | |
| // Moving Averages | |
| const maSignal = analysis.indicators.Moving_Averages.trend.toLowerCase(); | |
| container.innerHTML += ` | |
| <div class="indicator-card"> | |
| <h5>Moving Averages</h5> | |
| <div class="indicator-value">Trend</div> | |
| <span class="signal signal-${maSignal}">${analysis.indicators.Moving_Averages.trend}</span> | |
| </div> | |
| `; | |
| // Bollinger Bands | |
| container.innerHTML += ` | |
| <div class="indicator-card"> | |
| <h5>Bollinger Bands</h5> | |
| <div class="indicator-value">Position</div> | |
| <span class="signal signal-neutral">${analysis.indicators.Bollinger_Bands.position}</span> | |
| </div> | |
| `; | |
| } | |
| function updatePatternAnalysis(data) { | |
| const container = document.getElementById('patternAnalysis'); | |
| container.innerHTML = ''; | |
| // Support and Resistance | |
| container.innerHTML += ` | |
| <div class="mb-4"> | |
| <h5>Support & Resistance</h5> | |
| <div>Support Levels: ${data.support_resistance.support.map(level => '$' + level.toFixed(2)).join(', ')}</div> | |
| <div>Resistance Levels: ${data.support_resistance.resistance.map(level => '$' + level.toFixed(2)).join(', ')}</div> | |
| </div> | |
| `; | |
| // Risk Metrics | |
| container.innerHTML += ` | |
| <div class="mb-4"> | |
| <h5>Risk Metrics</h5> | |
| <div>Volatility: ${(data.risk_metrics.volatility * 100).toFixed(2)}%</div> | |
| <div>Sharpe Ratio: ${data.risk_metrics.sharpe_ratio.toFixed(2)}</div> | |
| <div>Max Drawdown: ${(data.risk_metrics.max_drawdown * 100).toFixed(2)}%</div> | |
| </div> | |
| `; | |
| } | |
| function updateSentimentAnalysis(data) { | |
| const container = document.getElementById('sentimentAnalysis'); | |
| const sentimentClass = data.sentiment_label === 'Positive' ? 'signal-bullish' : | |
| data.sentiment_label === 'Negative' ? 'signal-bearish' : 'signal-neutral'; | |
| container.innerHTML = ` | |
| <div class="mb-4"> | |
| <h5>Overall Sentiment</h5> | |
| <div class="indicator-value"> | |
| <span class="signal ${sentimentClass}">${data.sentiment_label}</span> | |
| </div> | |
| <div>Sentiment Score: ${data.average_sentiment.toFixed(2)}</div> | |
| </div> | |
| <div> | |
| <h5>Recent News Sentiment</h5> | |
| <div class="list-group"> | |
| ${data.articles.slice(0, 3).map(article => ` | |
| <div class="list-group-item"> | |
| <div class="d-flex justify-content-between"> | |
| <small>${new Date(article.date).toLocaleDateString()}</small> | |
| <span class="signal ${article.polarity > 0 ? 'signal-bullish' : article.polarity < 0 ? 'signal-bearish' : 'signal-neutral'}"> | |
| ${article.polarity > 0 ? 'Positive' : article.polarity < 0 ? 'Negative' : 'Neutral'} | |
| </span> | |
| </div> | |
| <div class="mt-1">${article.title}</div> | |
| </div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| `; | |
| } | |
| </script> | |
| </body> | |
| </html> |