Stock market dashboard with S&P 500, NASDAQ, Dow Jones indices, Apple stock chart, portfolio holdings, watchlist, and market news

Free Trade Tracker

Posted by

ยท

Trade Tracker * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, Roboto, sans-serif; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; color: #fff; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; } h1 { text-align: center; margin-bottom: 30px; font-size: 2.5rem; background: linear-gradient(90deg, #00d9ff, #00ff88); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .add-trade-form { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); border-radius: 16px; padding: 24px; margin-bottom: 30px; border: 1px solid rgba(255, 255, 255, 0.1); } .form-row { display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-end; } .form-group { flex: 1; min-width: 150px; } label { display: block; margin-bottom: 8px; font-size: 0.875rem; color: #aaa; text-transform: uppercase; letter-spacing: 0.5px; } input { width: 100%; padding: 12px 16px; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; background: rgba(255, 255, 255, 0.05); color: #fff; font-size: 1rem; transition: all 0.3s ease; } input:focus { outline: none; border-color: #00d9ff; box-shadow: 0 0 0 3px rgba(0, 217, 255, 0.2); } input::placeholder { color: #666; } button { padding: 12px 32px; border: none; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; } .btn-primary { background: linear-gradient(135deg, #00d9ff, #00ff88); color: #1a1a2e; } .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(0, 217, 255, 0.3); } .btn-danger { background: #ff4757; color: #fff; padding: 8px 16px; font-size: 0.875rem; } .btn-danger:hover { background: #ff3344; } .trades-container { display: grid; gap: 20px; } .trade-card { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); border-radius: 16px; padding: 24px; border: 1px solid rgba(255, 255, 255, 0.1); transition: all 0.3s ease; } .trade-card:hover { transform: translateY(-4px); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3); } .trade-card.profit { border-left: 4px solid #00ff88; } .trade-card.loss { border-left: 4px solid #ff4757; } .trade-card.target-hit { background: rgba(0, 255, 136, 0.1); border: 1px solid #00ff88; } .trade-card.sl-hit { background: rgba(255, 71, 87, 0.1); border: 1px solid #ff4757; } .trade-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .stock-symbol { font-size: 1.75rem; font-weight: 700; } .trade-status { padding: 6px 14px; border-radius: 20px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; } .status-active { background: rgba(0, 217, 255, 0.2); color: #00d9ff; } .status-target { background: rgba(0, 255, 136, 0.2); color: #00ff88; } .status-sl { background: rgba(255, 71, 87, 0.2); color: #ff4757; } .trade-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 16px; margin-bottom: 20px; } .detail-item { text-align: center; padding: 12px; background: rgba(0, 0, 0, 0.2); border-radius: 8px; } .detail-label { font-size: 0.75rem; color: #888; text-transform: uppercase; margin-bottom: 4px; } .detail-value { font-size: 1.25rem; font-weight: 600; } .current-price { color: #00d9ff; } .pnl-positive { color: #00ff88; } .pnl-negative { color: #ff4757; } .trade-footer { display: flex; justify-content: space-between; align-items: center; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.1); } .last-updated { font-size: 0.75rem; color: #666; } .no-trades { text-align: center; padding: 60px; color: #666; } .no-trades p { font-size: 1.25rem; margin-bottom: 8px; } .refresh-indicator { position: fixed; bottom: 20px; right: 20px; background: rgba(0, 217, 255, 0.2); color: #00d9ff; padding: 10px 20px; border-radius: 30px; font-size: 0.875rem; display: flex; align-items: center; gap: 8px; } .refresh-indicator.loading { animation: pulse 1s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .spinner { width: 16px; height: 16px; border: 2px solid transparent; border-top-color: #00d9ff; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .error-msg { background: rgba(255, 71, 87, 0.1); border: 1px solid #ff4757; color: #ff4757; padding: 12px 16px; border-radius: 8px; margin-top: 16px; display: none; } @media (max-width: 600px) { .form-row { flex-direction: column; } .form-group { width: 100%; } h1 { font-size: 1.75rem; } }

๐Ÿ“ˆ Trade Tracker

Stock Symbol
Buy Price
Target Price
Stop Loss
Quantity

No active trades

Add a trade above to start tracking
Updating prices…
// Trade storage let trades = JSON.parse(localStorage.getItem(‘trades’)) || []; // API Configuration – Using Yahoo Finance via a CORS proxy // For production, you’d want your own backend or a paid API const API_BASE = ‘[query1.finance.yahoo.com](https://query1.finance.yahoo.com/v8/finance/chart/)’; // Alternative free APIs to try: // 1. Alpha Vantage (needs free API key): [alphavantage.co](https://www.alphavantage.co/) // 2. Finnhub (needs free API key): [finnhub.io](https://finnhub.io/) // DOM Elements const tradeForm = document.getElementById(‘tradeForm’); const tradesContainer = document.getElementById(‘tradesContainer’); const refreshIndicator = document.getElementById(‘refreshIndicator’); const errorMsg = document.getElementById(‘errorMsg’); // Initialize document.addEventListener(‘DOMContentLoaded’, () => { renderTrades(); if (trades.length > 0) { updateAllPrices(); } // Auto-refresh every 30 seconds setInterval(updateAllPrices, 30000); }); // Add new trade tradeForm.addEventListener(‘submit’, async (e) => { e.preventDefault(); const symbol = document.getElementById(‘symbol’).value.toUpperCase().trim(); const buyPrice = parseFloat(document.getElementById(‘buyPrice’).value); const target = parseFloat(document.getElementById(‘target’).value); const stopLoss = parseFloat(document.getElementById(‘stopLoss’).value); const quantity = parseInt(document.getElementById(‘quantity’).value); // Validation if (target = buyPrice) { showError(‘Stop loss must be lower than buy price’); return; } const trade = { id: Date.now(), symbol, buyPrice, target, stopLoss, quantity, currentPrice: null, status: ‘active’, createdAt: new Date().toISOString(), lastUpdated: null }; // Try to fetch initial price showRefreshIndicator(true); const price = await fetchStockPrice(symbol); showRefreshIndicator(false); if (price) { trade.currentPrice = price; trade.lastUpdated = new Date().toISOString(); trade.status = getTradeStatus(trade); } trades.push(trade); saveTrades(); renderTrades(); tradeForm.reset(); document.getElementById(‘quantity’).value = 1; hideError(); }); // Fetch stock price async function fetchStockPrice(symbol) { try { // Using a CORS proxy for Yahoo Finance // In production, use your own backend const corsProxy = ‘[corsproxy.io](https://corsproxy.io/)’; const url = `${corsProxy}${encodeURIComponent(API_BASE + symbol)}`; const response = await fetch(url); const data = await response.json(); if (data.chart?.result?.[0]?.meta?.regularMarketPrice) { return data.chart.result[0].meta.regularMarketPrice; } // Fallback: try without .NS suffix for Indian stocks if (!symbol.includes(‘.’)) { const indianSymbol = symbol + ‘.NS’; const indiaUrl = `${corsProxy}${encodeURIComponent(API_BASE + indianSymbol)}`; const indiaResponse = await fetch(indiaUrl); const indiaData = await indiaResponse.json(); if (indiaData.chart?.result?.[0]?.meta?.regularMarketPrice) { // Update the trade symbol to include .NS return indiaData.chart.result[0].meta.regularMarketPrice; } } return null; } catch (error) { console.error(`Error fetching price for ${symbol}:`, error); return null; } } // Update all prices async function updateAllPrices() { if (trades.length === 0) return; showRefreshIndicator(true); for (const trade of trades) { if (trade.status === ‘active’) { const price = await fetchStockPrice(trade.symbol); if (price) { trade.currentPrice = price; trade.lastUpdated = new Date().toISOString(); trade.status = getTradeStatus(trade); } } } saveTrades(); renderTrades(); showRefreshIndicator(false); } // Get trade status function getTradeStatus(trade) { if (!trade.currentPrice) return ‘active’; if (trade.currentPrice >= trade.target) return ‘target-hit’; if (trade.currentPrice <= trade.stopLoss) return 'sl-hit'; return 'active'; } // Calculate P&L function calculatePnL(trade) { if (!trade.currentPrice) return { amount: 0, percentage: 0 }; const amount = (trade.currentPrice – trade.buyPrice) * trade.quantity; const percentage = ((trade.currentPrice – trade.buyPrice) / trade.buyPrice) * 100; return { amount, percentage }; } // Render trades function renderTrades() { if (trades.length === 0) { tradesContainer.innerHTML = `

No active trades

Add a trade above to start tracking
`; return; } tradesContainer.innerHTML = trades.map(trade => { const pnl = calculatePnL(trade); const isProfit = pnl.amount >= 0; const statusClass = trade.status === ‘target-hit’ ? ‘target-hit’ : trade.status === ‘sl-hit’ ? ‘sl-hit’ : isProfit ? ‘profit’ : ‘loss’; const statusBadgeClass = trade.status === ‘target-hit’ ? ‘status-target’ : trade.status === ‘sl-hit’ ? ‘status-sl’ : ‘status-active’; const statusText = trade.status === ‘target-hit’ ? ‘๐ŸŽฏ Target Hit’ : trade.status === ‘sl-hit’ ? ‘๐Ÿ›‘ SL Hit’ : ‘๐Ÿ”„ Active’; return `
${trade.symbol} ${statusText}
Buy Price
โ‚น${trade.buyPrice.toFixed(2)}
Current Price
${trade.currentPrice ? ‘โ‚น’ + trade.currentPrice.toFixed(2) : ‘Loading…’}
Target
โ‚น${trade.target.toFixed(2)}
Stop Loss
โ‚น${trade.stopLoss.toFixed(2)}
Quantity
${trade.quantity}
P&L
${isProfit ? ‘+’ : ”}โ‚น${pnl.amount.toFixed(2)}
(${isProfit ? ‘+’ : ”}${pnl.percentage.toFixed(2)}%)
`; }).join(”); } // Delete trade function deleteTrade(id) { trades = trades.filter(t => t.id !== id); saveTrades(); renderTrades(); } // Save to localStorage function saveTrades() { localStorage.setItem(‘trades’, JSON.stringify(trades)); } // UI Helpers function showRefreshIndicator(show) { refreshIndicator.style.display = show ? ‘flex’ : ‘none’; } function showError(msg) { errorMsg.textContent = msg; errorMsg.style.display = ‘block’; } function hideError() { errorMsg.style.display = ‘none’; }
PANKAJ KUMAR Avatar

About the author