UNPKG

maher-tradingview-api

Version:

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

566 lines (518 loc) 16.4 kB
/* eslint-disable linebreak-style */ /* eslint-disable no-restricted-properties */ /* eslint-disable linebreak-style */ /* eslint-disable no-unused-vars */ /* eslint-disable prefer-const */ /* eslint-disable linebreak-style */ /* eslint-disable space-before-function-paren */ /* eslint-disable no-const-assign */ /* eslint-disable arrow-parens */ /* eslint-disable no-use-before-define */ /* eslint-disable comma-dangle */ /* eslint-disable no-plusplus */ /* eslint-disable no-trailing-spaces */ /* eslint-disable object-shorthand */ /* eslint-disable func-names */ /* eslint-disable linebreak-style */ /* eslint-disable no-undef */ /* eslint-disable linebreak-style */ /** * technical-indicators.js * ملف رسم المؤشرات الفنية لتطبيق TradingView API */ // التحقق من تحميل مكتبة Chart.js وإضافاتها (function() { if (typeof Chart === 'undefined') { console.error('مكتبة Chart.js غير محملة'); return; } })(); // رسم مؤشر RSI (مؤشر القوة النسبية) function renderRSIChart(chartId, data, period = 14) { try { if (!data || !Array.isArray(data) || data.length === 0) { console.error('renderRSIChart: البيانات غير صالحة', data); return; } const chartElement = document.getElementById(chartId); if (!chartElement) { console.error(`renderRSIChart: لم يتم العثور على العنصر ${chartId}`); return; } const ctx = chartElement.getContext('2d'); const existingChart = Chart.getChart(ctx.canvas); if (existingChart) { existingChart.destroy(); } const rsiValues = calculateRSI(data, period); const labels = Array.from({ length: rsiValues.length }, (_, i) => i + 1); return new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [{ label: 'RSI', data: rsiValues, borderColor: '#0088cc', backgroundColor: 'rgba(0, 136, 204, 0.1)', borderWidth: 2, fill: true, pointRadius: 0, pointHoverRadius: 4 }] }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false }, scales: { x: { display: false }, y: { min: 0, max: 100, grid: { color: function(context) { if (context.tick.value === 30 || context.tick.value === 70) { return 'rgba(255, 0, 0, 0.1)'; } return 'rgba(0, 0, 0, 0.05)'; } }, ticks: { callback: function(value) { if (value === 0 || value === 30 || value === 70 || value === 100) { return value; } return ''; } } } }, plugins: { tooltip: { mode: 'index', intersect: false, callbacks: { label: function(context) { return `RSI: ${context.parsed.y.toFixed(2)}`; } } }, annotation: { annotations: { line70: { type: 'line', yMin: 70, yMax: 70, borderColor: 'rgba(255, 82, 82, 0.7)', borderWidth: 1, borderDash: [3, 3], label: { enabled: true, content: 'ذروة شراء', position: 'end', backgroundColor: 'rgba(255, 82, 82, 0.7)' } }, line30: { type: 'line', yMin: 30, yMax: 30, borderColor: 'rgba(75, 192, 192, 0.7)', borderWidth: 1, borderDash: [3, 3], label: { enabled: true, content: 'ذروة بيع', position: 'end', backgroundColor: 'rgba(75, 192, 192, 0.7)' } } } } } } }); } catch (error) { console.error('renderRSIChart: خطأ في رسم المؤشر', error); } } // رسم مؤشر MACD function renderMACDChart(chartId, data, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) { try { if (!data || !Array.isArray(data) || data.length === 0) { console.error('renderMACDChart: البيانات غير صالحة', data); return; } const chartElement = document.getElementById(chartId); if (!chartElement) { console.error(`renderMACDChart: لم يتم العثور على العنصر ${chartId}`); return; } const ctx = chartElement.getContext('2d'); const existingChart = Chart.getChart(ctx.canvas); if (existingChart) { existingChart.destroy(); } const macdData = calculateMACD(data, fastPeriod, slowPeriod, signalPeriod); const labels = Array.from({ length: macdData.macdLine.length }, (_, i) => i + 1); return new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [ { label: 'Histogram', data: macdData.histogram, type: 'bar', backgroundColor: function(context) { const value = context.dataset.data[context.dataIndex]; return value >= 0 ? 'rgba(75, 192, 192, 0.6)' : 'rgba(255, 99, 132, 0.6)'; }, order: 3 }, { label: 'MACD Line', data: macdData.macdLine, borderColor: '#0088cc', backgroundColor: 'transparent', borderWidth: 2, pointRadius: 0, order: 1 }, { label: 'Signal Line', data: macdData.signalLine, borderColor: '#ff6384', backgroundColor: 'transparent', borderWidth: 2, pointRadius: 0, order: 2 } ] }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false }, scales: { x: { display: false }, y: { grid: { color: 'rgba(0, 0, 0, 0.05)' } } }, plugins: { tooltip: { mode: 'index', intersect: false, callbacks: { label: function(context) { const datasetLabel = context.dataset.label; const value = context.parsed.y; return `${datasetLabel}: ${value.toFixed(4)}`; } } }, legend: { display: true, position: 'top', labels: { boxWidth: 12, padding: 15 } } } } }); } catch (error) { console.error('renderMACDChart: خطأ في رسم المؤشر', error); } } // رسم مؤشر المتوسط المتحرك function renderMAChart(chartId, data, periods = [20, 50, 200]) { try { if (!data || !Array.isArray(data) || data.length === 0) { console.error('renderMAChart: البيانات غير صالحة', data); return; } const chartElement = document.getElementById(chartId); if (!chartElement) { console.error(`renderMAChart: لم يتم العثور على العنصر ${chartId}`); return; } const ctx = chartElement.getContext('2d'); const existingChart = Chart.getChart(ctx.canvas); if (existingChart) { existingChart.destroy(); } const labels = Array.from({ length: data.length }, (_, i) => i + 1); const datasets = [{ label: 'السعر', data: data, borderColor: '#0088cc', backgroundColor: 'transparent', borderWidth: 2, pointRadius: 0, order: 1 }]; const colors = ['#ff6384', '#36a2eb', '#4bc0c0']; periods.forEach((period, index) => { const maValues = calculateSMA(data, period); const paddedMA = Array(period - 1).fill(null).concat(maValues); datasets.push({ label: `MA${period}`, data: paddedMA, borderColor: colors[index % colors.length], backgroundColor: 'transparent', borderWidth: 1.5, pointRadius: 0, borderDash: [5, 5], order: index + 2 }); }); return new Chart(ctx, { type: 'line', data: { labels, datasets }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false }, scales: { x: { display: false }, y: { grid: { color: 'rgba(0, 0, 0, 0.05)' } } }, plugins: { tooltip: { mode: 'index', intersect: false }, legend: { display: true, position: 'top' } } } }); } catch (error) { console.error('renderMAChart: خطأ في رسم المؤشر', error); } } // رسم مؤشر بولينجر باند function renderBollingerBandsChart(chartId, data, period = 20, stdDev = 2) { try { if (!data || !Array.isArray(data) || data.length === 0) { console.error('renderBollingerBandsChart: البيانات غير صالحة', data); return; } const chartElement = document.getElementById(chartId); if (!chartElement) { console.error(`renderBollingerBandsChart: لم يتم العثور على العنصر ${chartId}`); return; } const ctx = chartElement.getContext('2d'); const existingChart = Chart.getChart(ctx.canvas); if (existingChart) { existingChart.destroy(); } const { middle, upper, lower } = calculateBollingerBands(data, period, stdDev); const labels = Array.from({ length: data.length }, (_, i) => i + 1); // Pad the arrays to align with price data const padding = Array(period - 1).fill(null); const paddedMiddle = [...padding, ...middle]; const paddedUpper = [...padding, ...upper]; const paddedLower = [...padding, ...lower]; return new Chart(ctx, { type: 'line', data: { labels: labels, datasets: [ { label: 'السعر', data: data, borderColor: '#0088cc', backgroundColor: 'transparent', borderWidth: 2, pointRadius: 0, fill: false, order: 1 }, { label: `النطاق العلوي (${period}, ${stdDev})`, data: paddedUpper, borderColor: 'rgba(231, 76, 60, 0.8)', borderWidth: 1, borderDash: [3, 3], pointRadius: 0, fill: false, order: 2 }, { label: `النطاق المتوسط (${period})`, data: paddedMiddle, borderColor: 'rgba(46, 204, 113, 0.8)', borderWidth: 1, pointRadius: 0, fill: false, order: 3 }, { label: `النطاق السفلي (${period}, ${stdDev})`, data: paddedLower, borderColor: 'rgba(231, 76, 60, 0.8)', borderWidth: 1, borderDash: [3, 3], pointRadius: 0, fill: { target: 'origin', above: 'rgba(231, 76, 60, 0.05)', below: 'rgba(46, 204, 113, 0.05)' }, order: 4 } ] }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false }, scales: { x: { display: false }, y: { grid: { color: 'rgba(0, 0, 0, 0.05)' } } }, plugins: { tooltip: { mode: 'index', intersect: false }, legend: { display: true, position: 'top', labels: { boxWidth: 10, padding: 10 } } } } }); } catch (error) { console.error('renderBollingerBandsChart: خطأ في رسم المؤشر', error); } } // وظائف حساب المؤشرات الفنية // حساب مؤشر القوة النسبية (RSI) function 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 (const [i, gain] of gains.entries()) { const loss = losses[i]; lastAvgGain = (lastAvgGain * (period - 1) + gain) / period; lastAvgLoss = (lastAvgLoss * (period - 1) + loss) / period; rsi.push(100 - (100 / (1 + lastAvgGain / lastAvgLoss))); } return rsi; } // حساب مؤشر MACD function calculateMACD(data, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) { const fastEMA = calculateEMA(data, fastPeriod); const slowEMA = calculateEMA(data, slowPeriod); const macdLine = []; for (let i = 0; i < data.length; i++) { macdLine.push(fastEMA[i] - slowEMA[i]); } const signalLine = calculateEMA(macdLine, signalPeriod); const histogram = macdLine.map((macd, i) => macd - signalLine[i]); return { macdLine, signalLine, histogram }; } // حساب المتوسط المتحرك البسيط (SMA) function calculateSMA(data, period) { const sma = []; for (let i = period - 1; i < data.length; i++) { const sum = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0); sma.push(sum / period); } return sma; } // حساب المتوسط المتحرك الأسي (EMA) function calculateEMA(data, period) { const k = 2 / (period + 1); const ema = [data[0]]; for (let i = 1; i < data.length; i++) { ema.push(data[i] * k + ema[i - 1] * (1 - k)); } return ema; } // حساب مؤشر بولينجر باندز function calculateBollingerBands(data, period = 20, stdDev = 2) { const middle = []; const upper = []; const lower = []; 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 squareDiffs = slice.map(val => Math.pow(val - avg, 2)); const variance = squareDiffs.reduce((sum, val) => sum + val, 0) / period; const std = Math.sqrt(variance); middle.push(avg); upper.push(avg + (std * stdDev)); lower.push(avg - (std * stdDev)); } return { middle, upper, lower }; } // تصدير الوظائف للاستخدام العالمي window.TechnicalIndicators = { renderRSIChart, renderMACDChart, renderMAChart, renderBollingerBandsChart, calculateRSI, calculateMACD, calculateSMA, calculateEMA, calculateBollingerBands };