UNPKG

maher-tradingview-api

Version:

Tradingview instant stocks API, indicator alerts, trading bot, and more !

260 lines (222 loc) 8.86 kB
// Advanced Technical Indicators Implementation class AdvancedTechnicalIndicators { constructor() { this.indicators = new Map(); } // Calculate Exponential Moving Average (EMA) calculateEMA(data, period) { const k = 2 / (period + 1); let ema = data[0]; const result = [ema]; for (let i = 1; i < data.length; i++) { ema = data[i] * k + ema * (1 - k); result.push(ema); } return result; } // Calculate Relative Strength Index (RSI) calculateRSI(data, period = 14) { const changes = []; for (let i = 1; i < data.length; i++) { changes.push(data[i] - data[i - 1]); } let gains = changes.map(change => change > 0 ? change : 0); let losses = changes.map(change => change < 0 ? -change : 0); const avgGain = gains.slice(0, period).reduce((sum, val) => sum + val, 0) / period; const avgLoss = losses.slice(0, period).reduce((sum, val) => sum + val, 0) / period; gains = gains.slice(period); losses = losses.slice(period); const rsi = [100 - (100 / (1 + avgGain / avgLoss))]; let lastAvgGain = avgGain; let lastAvgLoss = avgLoss; for (let i = 0; i < gains.length; i++) { const gain = gains[i]; const loss = losses[i]; lastAvgGain = (lastAvgGain * (period - 1) + gain) / period; lastAvgLoss = (lastAvgLoss * (period - 1) + loss) / period; const rs = lastAvgGain / lastAvgLoss; rsi.push(100 - (100 / (1 + rs))); } return rsi; } // Calculate MACD calculateMACD(data, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) { const fastEMA = this.calculateEMA(data, fastPeriod); const slowEMA = this.calculateEMA(data, slowPeriod); const macdLine = fastEMA.map((fast, i) => fast - slowEMA[i]); const signalLine = this.calculateEMA(macdLine, signalPeriod); const histogram = macdLine.map((macd, i) => macd - signalLine[i]); return { macdLine, signalLine, histogram }; } // Calculate Bollinger Bands calculateBollingerBands(data, period = 20, standardDeviations = 2) { const sma = []; const upperBand = []; const lowerBand = []; for (let i = period - 1; i < data.length; i++) { const slice = data.slice(i - period + 1, i + 1); const avg = slice.reduce((sum, val) => sum + val, 0) / period; const stdDev = Math.sqrt( slice.reduce((sum, val) => sum + Math.pow(val - avg, 2), 0) / period ); sma.push(avg); upperBand.push(avg + standardDeviations * stdDev); lowerBand.push(avg - standardDeviations * stdDev); } return { middle: sma, upper: upperBand, lower: lowerBand }; } // Calculate Ichimoku Cloud calculateIchimoku(high, low, conversionPeriod = 9, basePeriod = 26, spanPeriod = 52, displacement = 26) { const conversion = []; const base = []; const spanA = []; const spanB = []; // Calculate Conversion Line (Tenkan-sen) for (let i = conversionPeriod - 1; i < high.length; i++) { const highSlice = high.slice(i - conversionPeriod + 1, i + 1); const lowSlice = low.slice(i - conversionPeriod + 1, i + 1); conversion.push((Math.max(...highSlice) + Math.min(...lowSlice)) / 2); } // Calculate Base Line (Kijun-sen) for (let i = basePeriod - 1; i < high.length; i++) { const highSlice = high.slice(i - basePeriod + 1, i + 1); const lowSlice = low.slice(i - basePeriod + 1, i + 1); base.push((Math.max(...highSlice) + Math.min(...lowSlice)) / 2); } // Calculate Leading Span A (Senkou Span A) for (let i = 0; i < conversion.length && i < base.length; i++) { spanA.push((conversion[i] + base[i]) / 2); } // Calculate Leading Span B (Senkou Span B) for (let i = spanPeriod - 1; i < high.length; i++) { const highSlice = high.slice(i - spanPeriod + 1, i + 1); const lowSlice = low.slice(i - spanPeriod + 1, i + 1); spanB.push((Math.max(...highSlice) + Math.min(...lowSlice)) / 2); } return { conversion, base, spanA: [...Array(displacement).fill(null), ...spanA], spanB: [...Array(displacement).fill(null), ...spanB] }; } // Calculate Volume Profile calculateVolumeProfile(prices, volumes, levels = 12) { const minPrice = Math.min(...prices); const maxPrice = Math.max(...prices); const priceRange = maxPrice - minPrice; const levelHeight = priceRange / levels; const profile = Array(levels).fill(0); const levelPrices = Array(levels).fill(0).map((_, i) => minPrice + levelHeight * i); prices.forEach((price, i) => { const levelIndex = Math.floor((price - minPrice) / levelHeight); if (levelIndex >= 0 && levelIndex < levels) { profile[levelIndex] += volumes[i]; } }); return { profile, levelPrices }; } // Render Advanced Indicators renderAdvancedIndicator(canvasId, type, data, options = {}) { const existingIndicator = this.indicators.get(canvasId); if (existingIndicator) { existingIndicator.destroy(); } const ctx = document.getElementById(canvasId)?.getContext('2d'); if (!ctx) return; let chartConfig; switch (type) { case 'ichimoku': chartConfig = this.createIchimokuConfig(data, options); break; case 'volumeProfile': chartConfig = this.createVolumeProfileConfig(data, options); break; default: console.warn(`Unknown indicator type: ${type}`); return; } const chart = new Chart(ctx, chartConfig); this.indicators.set(canvasId, chart); return chart; } // Create Ichimoku Cloud Configuration createIchimokuConfig(data, options) { return { type: 'line', data: { labels: data.labels, datasets: [ { label: 'Conversion Line', data: data.conversion, borderColor: '#2196F3', fill: false, pointRadius: 0 }, { label: 'Base Line', data: data.base, borderColor: '#FF5722', fill: false, pointRadius: 0 }, { label: 'Leading Span A', data: data.spanA, borderColor: '#4CAF50', fill: false, pointRadius: 0 }, { label: 'Leading Span B', data: data.spanB, borderColor: '#FFC107', fill: false, pointRadius: 0 } ] }, options: { ...options, responsive: true, maintainAspectRatio: false } }; } // Create Volume Profile Configuration createVolumeProfileConfig(data, options) { return { type: 'bar', data: { labels: data.levelPrices.map(price => price.toFixed(2)), datasets: [{ label: 'Volume Profile', data: data.profile, backgroundColor: 'rgba(0, 136, 204, 0.5)', borderColor: 'rgba(0, 136, 204, 1)', borderWidth: 1 }] }, options: { ...options, responsive: true, maintainAspectRatio: false, indexAxis: 'y' } }; } } // Export the advanced indicators window.AdvancedTechnicalIndicators = new AdvancedTechnicalIndicators();