--- description: Track real-time prices across crypto, stocks, forex, and commodities with multi-source feeds shortcut: tp --- # Track Market Price Real-time price tracking system with institutional-grade data feeds from multiple sources for accuracy and reliability. ## Usage When the user wants to track market prices, implement a comprehensive price monitoring system with these capabilities: ### Required Information - **Symbol**: Asset ticker (BTC, AAPL, EUR/USD, etc.) - **Asset Type**: crypto, stock, forex, commodity - **Interval**: 1s, 5s, 30s, 1m, 5m (real-time streaming) - **Exchanges**: Specific exchanges or "ALL" for aggregate - **Alert Conditions**: Price thresholds, percentage changes - **Duration**: How long to track (continuous or time-limited) ## Implementation ### 1. Multi-Source Price Aggregator ```javascript class MarketPriceTracker { constructor() { this.dataSources = { crypto: { binance: 'wss://stream.binance.com:9443/ws', coinbase: 'wss://ws-feed.exchange.coinbase.com', kraken: 'wss://ws.kraken.com', ftx: 'wss://ftx.com/ws/', coingecko: 'https://api.coingecko.com/api/v3', messari: 'https://data.messari.io/api/v1' }, stocks: { alphaVantage: process.env.ALPHA_VANTAGE_API, iex: 'https://api.iextrading.com/1.0', polygon: 'wss://socket.polygon.io', finnhub: 'wss://ws.finnhub.io', yahoo: 'https://query1.finance.yahoo.com/v8' }, forex: { oanda: 'wss://stream-fxtrade.oanda.com', forexConnect: 'https://api-fxtrade.oanda.com/v3', currencyLayer: process.env.CURRENCY_LAYER_API, exchangeRates: 'https://api.exchangerate.host' }, commodities: { quandl: process.env.QUANDL_API, metalsPrices: 'https://api.metals.live/v1', oilPrices: 'https://api.oilpriceapi.com/v1' } }; this.priceCache = new Map(); this.connections = new Map(); this.aggregationStrategy = 'VWAP'; // Volume Weighted Average Price } async trackPrice(params) { const { symbol, assetType, interval = '1s', exchanges = 'ALL', alertConditions = [], duration = 'continuous' } = params; // Validate symbol format this.validateSymbol(symbol, assetType); // Initialize tracking const trackingSession = { id: crypto.randomUUID(), symbol, assetType, interval, startTime: Date.now(), duration, exchanges: this.selectExchanges(exchanges, assetType), alerts: this.parseAlertConditions(alertConditions), priceHistory: [], statistics: { high: 0, low: Infinity, open: 0, volume: 0, vwap: 0, changes: { '1m': 0, '5m': 0, '15m': 0, '1h': 0, '24h': 0 } } }; // Start real-time tracking await this.initializeConnections(trackingSession); // Begin price aggregation this.startPriceAggregation(trackingSession); // Monitor alerts this.startAlertMonitoring(trackingSession); return trackingSession; } async initializeConnections(session) { const connections = []; for (const exchange of session.exchanges) { try { const connection = await this.connectToExchange( exchange, session.symbol, session.assetType ); connections.push({ exchange, connection, status: 'connected', latency: 0, lastUpdate: null }); // Subscribe to price updates this.subscribeToPrice(connection, session); } catch (error) { console.error(`Failed to connect to ${exchange}:`, error); connections.push({ exchange, status: 'failed', error: error.message }); } } session.connections = connections; return connections; } async connectToExchange(exchange, symbol, assetType) { const sourceConfig = this.dataSources[assetType][exchange]; if (sourceConfig.startsWith('wss://')) { // WebSocket connection return this.createWebSocketConnection(sourceConfig, symbol, exchange); } else { // REST API polling return this.createPollingConnection(sourceConfig, symbol, exchange); } } createWebSocketConnection(url, symbol, exchange) { return new Promise((resolve, reject) => { const ws = new WebSocket(url); ws.on('open', () => { // Subscribe to symbol const subscribeMsg = this.getSubscribeMessage(exchange, symbol); ws.send(JSON.stringify(subscribeMsg)); resolve(ws); }); ws.on('error', reject); ws.on('message', (data) => { this.handlePriceUpdate(exchange, data); }); }); } getSubscribeMessage(exchange, symbol) { const messages = { binance: { method: 'SUBSCRIBE', params: [`${symbol.toLowerCase()}@trade`, `${symbol.toLowerCase()}@depth`], id: 1 }, coinbase: { type: 'subscribe', product_ids: [symbol], channels: ['ticker', 'level2'] }, kraken: { event: 'subscribe', pair: [symbol], subscription: { name: 'ticker' } } }; return messages[exchange] || {}; } handlePriceUpdate(exchange, data) { const parsed = JSON.parse(data); const price = this.extractPrice(exchange, parsed); if (price) { const update = { exchange, price: price.price, volume: price.volume, timestamp: Date.now(), bid: price.bid, ask: price.ask, spread: price.ask - price.bid }; // Update cache if (!this.priceCache.has(exchange)) { this.priceCache.set(exchange, []); } this.priceCache.get(exchange).push(update); // Trigger aggregation this.aggregatePrices(); } } extractPrice(exchange, data) { const extractors = { binance: (d) => ({ price: parseFloat(d.p), volume: parseFloat(d.q), bid: parseFloat(d.b), ask: parseFloat(d.a) }), coinbase: (d) => ({ price: parseFloat(d.price), volume: parseFloat(d.volume_24h), bid: parseFloat(d.best_bid), ask: parseFloat(d.best_ask) }), kraken: (d) => ({ price: parseFloat(d[1].c[0]), volume: parseFloat(d[1].v[1]), bid: parseFloat(d[1].b[0]), ask: parseFloat(d[1].a[0]) }) }; return extractors[exchange]?.(data); } aggregatePrices() { const allPrices = []; for (const [exchange, prices] of this.priceCache.entries()) { if (prices.length > 0) { const recent = prices.filter(p => Date.now() - p.timestamp < 5000 // Last 5 seconds ); allPrices.push(...recent); } } if (allPrices.length === 0) return null; // Calculate aggregated price based on strategy let aggregatedPrice; switch (this.aggregationStrategy) { case 'VWAP': aggregatedPrice = this.calculateVWAP(allPrices); break; case 'MEDIAN': aggregatedPrice = this.calculateMedian(allPrices); break; case 'WEIGHTED': aggregatedPrice = this.calculateWeightedAverage(allPrices); break; default: aggregatedPrice = this.calculateSimpleAverage(allPrices); } return { price: aggregatedPrice, sources: allPrices.length, timestamp: Date.now(), spread: this.calculateSpread(allPrices), confidence: this.calculateConfidence(allPrices) }; } calculateVWAP(prices) { let totalValue = 0; let totalVolume = 0; for (const p of prices) { totalValue += p.price * p.volume; totalVolume += p.volume; } return totalVolume > 0 ? totalValue / totalVolume : 0; } calculateConfidence(prices) { if (prices.length < 2) return 0; const values = prices.map(p => p.price); const mean = values.reduce((a, b) => a + b) / values.length; const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length; const stdDev = Math.sqrt(variance); const coefficientOfVariation = (stdDev / mean) * 100; // Lower CV means higher confidence if (coefficientOfVariation < 0.5) return 99; if (coefficientOfVariation < 1) return 95; if (coefficientOfVariation < 2) return 90; if (coefficientOfVariation < 5) return 75; return 50; } startAlertMonitoring(session) { const checkInterval = this.parseInterval(session.interval); session.alertMonitor = setInterval(() => { const currentPrice = this.getCurrentPrice(session.symbol); if (!currentPrice) return; for (const alert of session.alerts) { if (this.checkAlertCondition(alert, currentPrice, session)) { this.triggerAlert(alert, currentPrice, session); } } }, checkInterval); } checkAlertCondition(alert, price, session) { switch (alert.type) { case 'PRICE_ABOVE': return price.price > alert.threshold; case 'PRICE_BELOW': return price.price < alert.threshold; case 'PERCENT_CHANGE': const changePercent = this.calculatePercentChange( session.statistics.open, price.price ); return Math.abs(changePercent) > alert.threshold; case 'VOLUME_SPIKE': return price.volume > session.statistics.avgVolume * alert.multiplier; case 'SPREAD_WIDE': return price.spread > alert.threshold; case 'VOLATILITY': return this.calculateVolatility(session) > alert.threshold; default: return false; } } triggerAlert(alert, price, session) { const alertData = { id: crypto.randomUUID(), type: alert.type, symbol: session.symbol, price: price.price, threshold: alert.threshold, timestamp: Date.now(), message: this.formatAlertMessage(alert, price, session), severity: alert.severity || 'INFO', action: alert.action || 'NOTIFY' }; // Send alert through notification channels this.sendAlert(alertData); // Log alert if (!session.triggeredAlerts) { session.triggeredAlerts = []; } session.triggeredAlerts.push(alertData); // Execute automated actions if configured if (alert.action === 'AUTO_TRADE') { this.executeAutomatedAction(alert, price, session); } } } ``` ### 2. Price Display Interface ```javascript class PriceDisplay { constructor() { this.displayMode = 'detailed'; // 'simple', 'detailed', 'professional' this.updateFrequency = 1000; // milliseconds } displayPrice(session, aggregatedPrice) { const display = ` ╔════════════════════════════════════════════════════════════════╗ ║ REAL-TIME PRICE TRACKER ║ ╠════════════════════════════════════════════════════════════════╣ ║ Symbol: ${session.symbol.padEnd(48)} ║ ║ Asset Type: ${session.assetType.padEnd(48)} ║ ║ Current Price: ${this.formatPrice(aggregatedPrice.price).padEnd(48)} ║ ║ Confidence: ${this.formatConfidence(aggregatedPrice.confidence).padEnd(48)} ║ ╠════════════════════════════════════════════════════════════════╣ ║ PRICE METRICS ║ ╠════════════════════════════════════════════════════════════════╣ ║ 24H High: ${this.formatPrice(session.statistics.high).padEnd(48)} ║ ║ 24H Low: ${this.formatPrice(session.statistics.low).padEnd(48)} ║ ║ 24H Change: ${this.formatChange(session.statistics.changes['24h']).padEnd(48)} ║ ║ Volume: ${this.formatVolume(session.statistics.volume).padEnd(48)} ║ ║ VWAP: ${this.formatPrice(session.statistics.vwap).padEnd(48)} ║ ╠════════════════════════════════════════════════════════════════╣ ║ EXCHANGE PRICES ║ ╠════════════════════════════════════════════════════════════════╣ ${this.formatExchangePrices(session)} ╠════════════════════════════════════════════════════════════════╣ ║ ALERTS ║ ╠════════════════════════════════════════════════════════════════╣ ${this.formatAlerts(session)} ╚════════════════════════════════════════════════════════════════╝ `; return display; } formatExchangePrices(session) { const lines = []; for (const conn of session.connections) { if (conn.status === 'connected' && conn.lastPrice) { lines.push(`║ ${conn.exchange.padEnd(15)} ${this.formatPrice(conn.lastPrice).padEnd(15)} ${this.formatLatency(conn.latency).padEnd(26)} ║`); } } return lines.join('\n'); } formatAlerts(session) { if (!session.alerts || session.alerts.length === 0) { return '║ No active alerts ║'; } const lines = []; for (const alert of session.alerts) { const status = alert.triggered ? '' : '⏳'; lines.push(`║ ${status} ${alert.type}: ${alert.threshold} ║`); } return lines.join('\n'); } formatPrice(price) { if (price > 1000) { return `$${price.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } else if (price > 1) { return `$${price.toFixed(4)}`; } else { return `$${price.toFixed(8)}`; } } formatConfidence(confidence) { const bars = '█'.repeat(Math.floor(confidence / 10)); const empty = '░'.repeat(10 - Math.floor(confidence / 10)); return `${bars}${empty} ${confidence}%`; } } ``` ### 3. Advanced Analytics ```javascript class PriceAnalytics { constructor() { this.indicators = {}; this.patterns = []; } analyzePrice(priceHistory) { return { technicalIndicators: this.calculateTechnicalIndicators(priceHistory), pricePatterns: this.detectPatterns(priceHistory), supportResistance: this.findSupportResistance(priceHistory), volatility: this.analyzeVolatility(priceHistory), momentum: this.analyzeMomentum(priceHistory), marketStructure: this.analyzeMarketStructure(priceHistory) }; } calculateTechnicalIndicators(prices) { return { sma: { sma20: this.calculateSMA(prices, 20), sma50: this.calculateSMA(prices, 50), sma200: this.calculateSMA(prices, 200) }, ema: { ema12: this.calculateEMA(prices, 12), ema26: this.calculateEMA(prices, 26) }, rsi: this.calculateRSI(prices, 14), macd: this.calculateMACD(prices), bollingerBands: this.calculateBollingerBands(prices, 20, 2), atr: this.calculateATR(prices, 14), obv: this.calculateOBV(prices), vwap: this.calculateDailyVWAP(prices) }; } detectPatterns(prices) { const patterns = []; // Head and Shoulders if (this.detectHeadAndShoulders(prices)) { patterns.push({ type: 'HEAD_AND_SHOULDERS', direction: 'BEARISH', confidence: 85 }); } // Double Top/Bottom const doublePattern = this.detectDoubleTopBottom(prices); if (doublePattern) { patterns.push(doublePattern); } // Triangle Patterns const triangle = this.detectTriangle(prices); if (triangle) { patterns.push(triangle); } // Flag/Pennant const flagPattern = this.detectFlagPennant(prices); if (flagPattern) { patterns.push(flagPattern); } return patterns; } findSupportResistance(prices) { const levels = []; const priceValues = prices.map(p => p.price); // Find local maxima and minima for (let i = 2; i < priceValues.length - 2; i++) { // Resistance (local maximum) if (priceValues[i] > priceValues[i-1] && priceValues[i] > priceValues[i-2] && priceValues[i] > priceValues[i+1] && priceValues[i] > priceValues[i+2]) { levels.push({ type: 'RESISTANCE', price: priceValues[i], strength: this.calculateLevelStrength(prices, priceValues[i]), touches: this.countTouches(prices, priceValues[i]) }); } // Support (local minimum) if (priceValues[i] < priceValues[i-1] && priceValues[i] < priceValues[i-2] && priceValues[i] < priceValues[i+1] && priceValues[i] < priceValues[i+2]) { levels.push({ type: 'SUPPORT', price: priceValues[i], strength: this.calculateLevelStrength(prices, priceValues[i]), touches: this.countTouches(prices, priceValues[i]) }); } } // Cluster similar levels return this.clusterLevels(levels); } } ``` ### 4. Alert Configuration ```javascript class AlertConfiguration { parseAlertConditions(conditions) { const parsed = []; for (const condition of conditions) { if (typeof condition === 'string') { // Parse string format: "above 50000", "below 45000", "change 5%" const match = condition.match(/(\w+)\s+([0-9.]+)(%)?/); if (match) { parsed.push(this.createAlert(match[1], parseFloat(match[2]), match[3] === '%')); } } else { // Object format already parsed.push(condition); } } return parsed; } createAlert(type, value, isPercent) { const alertTypes = { 'above': 'PRICE_ABOVE', 'below': 'PRICE_BELOW', 'change': 'PERCENT_CHANGE', 'volume': 'VOLUME_SPIKE', 'spread': 'SPREAD_WIDE', 'volatility': 'VOLATILITY' }; return { type: alertTypes[type] || 'CUSTOM', threshold: value, isPercent, enabled: true, cooldown: 300000, // 5 minutes between repeat alerts lastTriggered: 0 }; } } ``` ### 5. WebSocket Manager ```javascript class WebSocketManager { constructor() { this.connections = new Map(); this.reconnectAttempts = new Map(); this.maxReconnectAttempts = 5; this.reconnectDelay = 1000; } async manage(url, handlers) { const ws = new WebSocket(url); const connectionId = crypto.randomUUID(); ws.on('open', () => { console.log(`WebSocket connected: ${url}`); this.connections.set(connectionId, ws); this.reconnectAttempts.set(connectionId, 0); handlers.onOpen?.(ws); }); ws.on('message', (data) => { handlers.onMessage?.(data); }); ws.on('error', (error) => { console.error(`WebSocket error: ${url}`, error); handlers.onError?.(error); }); ws.on('close', () => { console.log(`WebSocket closed: ${url}`); this.connections.delete(connectionId); this.attemptReconnect(url, handlers, connectionId); }); return connectionId; } attemptReconnect(url, handlers, connectionId) { const attempts = this.reconnectAttempts.get(connectionId) || 0; if (attempts < this.maxReconnectAttempts) { const delay = this.reconnectDelay * Math.pow(2, attempts); console.log(`Reconnecting in ${delay}ms... (attempt ${attempts + 1})`); setTimeout(() => { this.reconnectAttempts.set(connectionId, attempts + 1); this.manage(url, handlers); }, delay); } else { console.error(`Max reconnection attempts reached for ${url}`); handlers.onMaxReconnectFailed?.(); } } } ``` ## Error Handling ```javascript try { const tracker = new MarketPriceTracker(); const session = await tracker.trackPrice({ symbol: 'BTC/USDT', assetType: 'crypto', interval: '1s', exchanges: ['binance', 'coinbase', 'kraken'], alertConditions: [ 'above 50000', 'below 45000', 'change 5%', 'volume 2x' ], duration: '24h' }); // Display real-time updates const display = new PriceDisplay(); setInterval(async () => { const price = tracker.getCurrentPrice(session.symbol); console.clear(); console.log(display.displayPrice(session, price)); }, 1000); } catch (error) { console.error('Price tracking failed:', error); process.exit(1); } ``` This command provides institutional-grade real-time price tracking with multi-exchange aggregation, advanced alerts, and comprehensive analytics.