Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>MarketLens</title> | |
| <link rel="stylesheet" href="styles.css"> | |
| </head> | |
| <body> | |
| <header class="global-header"> | |
| <div class="header-content"> | |
| <h1>MarketLens</h1> | |
| <div class="header-actions"> | |
| <div id="marketStatus" class="market-status"> | |
| <span class="status-label">Market:</span> | |
| <span id="marketStatusText" class="status-text">Loading...</span> | |
| </div> | |
| <button id="themeToggle" class="theme-toggle" aria-label="Toggle dark mode"> | |
| <svg class="icon-moon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /> | |
| </svg> | |
| <svg class="icon-sun" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="app-layout"> | |
| <main class="main-content"> | |
| <div class="ticker-selector"> | |
| <label for="tickerSearch">Select a Stock:</label> | |
| <div class="dropdown-container"> | |
| <input type="text" | |
| id="tickerSearch" | |
| placeholder="Search ticker or company name..." | |
| autocomplete="off"> | |
| <div id="dropdownList" class="dropdown-list hidden"></div> | |
| </div> | |
| </div> | |
| <div id="stockData" class="stock-data hidden"> | |
| <div class="stock-header"> | |
| <h2 id="stockTitle"></h2> | |
| <div id="stockPrice" class="stock-price"></div> | |
| </div> | |
| <div class="tabs"> | |
| <button class="tab-button active" data-tab="overview">Overview</button> | |
| <button class="tab-button" data-tab="financials">Financials</button> | |
| <button class="tab-button" data-tab="dividends">Dividends</button> | |
| <button class="tab-button" data-tab="splits">Splits</button> | |
| <button class="tab-button" data-tab="news">News</button> | |
| <button class="tab-button" data-tab="sentiment">Sentiment</button> | |
| <button class="tab-button" data-tab="forecast">Forecast <span class="beta-tag">Beta</span></button> | |
| </div> | |
| <div class="tab-content"> | |
| <div id="overview" class="tab-pane active"> | |
| <div class="chart-section"> | |
| <h3>Price Chart</h3> | |
| <div class="chart-controls"> | |
| <button class="chart-range-btn active" data-range="1M">1M</button> | |
| <button class="chart-range-btn" data-range="3M">3M</button> | |
| <button class="chart-range-btn" data-range="6M">6M</button> | |
| <button class="chart-range-btn" data-range="1Y">1Y</button> | |
| <button class="chart-range-btn" data-range="5Y">5Y</button> | |
| <div class="chart-controls-spacer"></div> | |
| <div class="chart-view-toggle"> | |
| <button class="chart-view-btn active" data-view="line">Line</button> | |
| <button class="chart-view-btn" data-view="candle">Candle</button> | |
| </div> | |
| </div> | |
| <div class="chart-canvas-wrapper"> | |
| <canvas id="priceChart"></canvas> | |
| <div id="chartLoading" class="chart-loading hidden"> | |
| <div class="spinner"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="metrics-grid"> | |
| <div class="metric-card"> | |
| <div class="metric-label">Open</div> | |
| <div class="metric-value" id="openPrice">--</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-label">High</div> | |
| <div class="metric-value" id="highPrice">--</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-label">Low</div> | |
| <div class="metric-value" id="lowPrice">--</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-label">Volume</div> | |
| <div class="metric-value" id="volume">--</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-label">Market Cap</div> | |
| <div class="metric-value" id="marketCap">--</div> | |
| </div> | |
| <div class="metric-card"> | |
| <div class="metric-label">P/E Ratio</div> | |
| <div class="metric-value" id="peRatio">--</div> | |
| </div> | |
| </div> | |
| <div class="company-description"> | |
| <h3>Company Description</h3> | |
| <p id="companyDesc">--</p> | |
| </div> | |
| </div> | |
| <div id="financials" class="tab-pane"> | |
| <div id="financialsData"> | |
| <p>Loading financial data...</p> | |
| </div> | |
| </div> | |
| <div id="dividends" class="tab-pane"> | |
| <div id="dividendsContainer"> | |
| <p>Loading dividend data...</p> | |
| </div> | |
| </div> | |
| <div id="splits" class="tab-pane"> | |
| <div id="splitsContainer"> | |
| <p>Loading stock split data...</p> | |
| </div> | |
| </div> | |
| <div id="news" class="tab-pane"> | |
| <div id="newsContainer"> | |
| <p>Loading news...</p> | |
| </div> | |
| </div> | |
| <div id="sentiment" class="tab-pane"> | |
| <div class="sentiment-header"> | |
| <div class="sentiment-aggregate"> | |
| <div class="sentiment-score-container"> | |
| <div class="sentiment-gauge" id="sentimentGauge"> | |
| <div class="gauge-background"></div> | |
| <div class="gauge-fill" id="gaugeFill"></div> | |
| <div class="gauge-needle" id="gaugeNeedle"></div> | |
| <div class="gauge-center"></div> | |
| </div> | |
| <div class="sentiment-label" id="sentimentLabel">--</div> | |
| </div> | |
| <div class="sentiment-stats"> | |
| <div class="stat-item"> | |
| <span class="stat-label">Posts Analyzed</span> | |
| <span class="stat-value" id="sentimentPostCount">--</span> | |
| </div> | |
| <div class="stat-item"> | |
| <span class="stat-label">Last Updated</span> | |
| <span class="stat-value" id="sentimentLastUpdated">--</span> | |
| </div> | |
| </div> | |
| </div> | |
| <button class="refresh-btn" id="sentimentRefreshBtn" title="Re-scrape and re-analyze"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg> | |
| Refresh | |
| </button> | |
| </div> | |
| <div class="sentiment-sources"> | |
| <h4>Sources</h4> | |
| <div class="source-breakdown"> | |
| <div class="source-item" id="stocktwitsSource"> | |
| <span class="source-icon">📈</span> | |
| <span class="source-name">Stocktwits</span> | |
| <span class="source-count">--</span> | |
| </div> | |
| <div class="source-item" id="redditSource"> | |
| <span class="source-icon">👽</span> | |
| <span class="source-name">Reddit</span> | |
| <span class="source-count">--</span> | |
| </div> | |
| <div class="source-item" id="twitterSource"> | |
| <span class="source-icon">🐦</span> | |
| <span class="source-name">Twitter/X</span> | |
| <span class="source-count">--</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="sentiment-posts-section"> | |
| <div class="posts-header"> | |
| <h4>Recent Posts</h4> | |
| <div class="posts-filter"> | |
| <button class="filter-btn active" data-filter="all">All</button> | |
| <button class="filter-btn" data-filter="positive">Bullish</button> | |
| <button class="filter-btn" data-filter="negative">Bearish</button> | |
| </div> | |
| </div> | |
| <div id="sentimentPostsContainer"> | |
| <p class="loading-text">Select a stock to analyze sentiment...</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="forecast" class="tab-pane"> | |
| <div class="forecast-header"> | |
| <div class="forecast-info"> | |
| <h4>Price Forecast</h4> | |
| <p class="forecast-description"> | |
| LSTM neural network prediction based on historical price patterns | |
| </p> | |
| </div> | |
| <div class="forecast-controls"> | |
| <div class="forecast-status"> | |
| <div class="status-item"> | |
| <span class="status-label">Model Status</span> | |
| <span class="status-value" id="forecastModelStatus">Not trained</span> | |
| </div> | |
| <div class="status-item"> | |
| <span class="status-label">Last Updated</span> | |
| <span class="status-value" id="forecastLastUpdated">--</span> | |
| </div> | |
| </div> | |
| <div class="forecast-actions"> | |
| <button class="refresh-btn" id="forecastRefreshBtn" title="Re-train model and re-predict"> | |
| <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg> | |
| Refresh | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="forecastTableContainer"></div> | |
| <div class="forecast-chart-section"> | |
| <div class="chart-legend"> | |
| <span class="legend-item historical"> | |
| <span class="legend-color"></span> Historical | |
| </span> | |
| <span class="legend-item predicted"> | |
| <span class="legend-color"></span> Predicted | |
| </span> | |
| <span class="legend-item confidence"> | |
| <span class="legend-color"></span> Confidence Band | |
| </span> | |
| </div> | |
| <canvas id="forecastChart"></canvas> | |
| </div> | |
| <div class="forecast-disclaimer"> | |
| <p> | |
| <strong>Disclaimer:</strong> These predictions are generated by a machine learning model | |
| for educational purposes only. Past performance does not guarantee future results. | |
| This is not financial advice. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="loading" class="loading hidden"> | |
| <div class="spinner"></div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Chat Panel --> | |
| <aside class="chat-panel" id="chatPanel"> | |
| <div class="chat-panel-content"> | |
| <div class="chat-header"> | |
| <h3>AI Assistant</h3> | |
| <button id="closeMobileChat" class="close-mobile-chat" aria-label="Close chat"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <line x1="18" y1="6" x2="6" y2="18"></line> | |
| <line x1="6" y1="6" x2="18" y2="18"></line> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="chat-ticker-context"> | |
| <span id="chatCurrentTicker">Select a stock to start</span> | |
| </div> | |
| <div id="chatMessages" class="chat-messages"> | |
| <!-- Messages populated dynamically --> | |
| </div> | |
| <div class="chat-input-container"> | |
| <textarea id="chatInput" | |
| placeholder="Ask about this stock..." | |
| rows="2"></textarea> | |
| <button id="sendChatBtn" class="send-chat-btn">Send</button> | |
| </div> | |
| </div> | |
| </aside> | |
| </div> | |
| <!-- Mobile Chat Toggle (visible on small screens only) --> | |
| <button id="mobileChatToggle" class="mobile-chat-toggle" aria-label="Toggle chat"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> | |
| </svg> | |
| </button> | |
| <script src="app.js"></script> | |
| </body> | |
| </html> | |