Front

# تطبيق تحليل مالي للبيانات من Investing ## مكونات المشروع ### 1. الواجهة الأمامية (HTML, CSS, JavaScript) #### index.html ```html محلل البيانات المالية

محلل البيانات المالية

تحميل ملف CSV من Investing

خيارات التحليل

``` #### style.css ```css @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700&display=swap'); :root { --primary-color: #2c73d2; --secondary-color: #4e8fef; --background-color: #f8f9fa; --text-color: #333; --border-color: #ddd; --shadow-color: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Tajawal', sans-serif; background-color: var(--background-color); color: var(--text-color); line-height: 1.6; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; } h1, h2, h3 { margin-bottom: 20px; color: var(--primary-color); } h1 { text-align: center; font-size: 2.5rem; margin: 1.5rem 0; } .upload-section { background: white; border-radius: 10px; padding: 30px; box-shadow: 0 5px 15px var(--shadow-color); margin-bottom: 30px; } .file-upload { margin: 20px 0; } .file-upload input[type="file"] { position: absolute; width: 0; height: 0; overflow: hidden; } .file-upload label { display: inline-block; padding: 12px 24px; background: var(--primary-color); color: white; border-radius: 5px; cursor: pointer; transition: background 0.3s; } .file-upload label:hover { background: var(--secondary-color); } .options { margin: 20px 0; } .option { margin: 10px 0; display: flex; align-items: center; } .option input[type="checkbox"] { margin-left: 10px; } button { display: block; width: 100%; padding: 12px; background: var(--primary-color); color: white; border: none; border-radius: 5px; font-size: 1rem; cursor: pointer; transition: background 0.3s; } button:hover { background: var(--secondary-color); } button:disabled { background: #ccc; cursor: not-allowed; } .results { background: white; border-radius: 10px; padding: 30px; box-shadow: 0 5px 15px var(--shadow-color); } .charts { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 30px; } .chart-container { flex: 1 1 100%; min-height: 300px; border: 1px solid var(--border-color); border-radius: 5px; padding: 15px; } @media (min-width: 768px) { .chart-container { flex: 1 1 45%; } } .stats, .recommendations { margin-top: 30px; padding: 20px; border: 1px solid var(--border-color); border-radius: 5px; } #statsContent, #recommendationsContent { display: grid; grid-template-columns: 1fr; gap: 15px; } @media (min-width: 768px) { #statsContent, #recommendationsContent { grid-template-columns: 1fr 1fr; } } .stat-item, .recommendation-item { padding: 15px; background: #f5f7fa; border-radius: 5px; box-shadow: 0 2px 5px var(--shadow-color); } .stat-value { font-weight: bold; font-size: 1.1rem; color: var(--primary-color); } ``` #### app.js ```javascript document.addEventListener('DOMContentLoaded', function() { const csvFileInput = document.getElementById('csvFile'); const analyzeBtn = document.getElementById('analyzeBtn'); const resultsSection = document.getElementById('results'); // Charts let priceChart = null; let indicatorsChart = null; csvFileInput.addEventListener('change', function() { if (this.files.length > 0) { analyzeBtn.disabled = false; } else { analyzeBtn.disabled = true; } }); analyzeBtn.addEventListener('click', function() { const file = csvFileInput.files[0]; if (file) { // Parse the CSV file Papa.parse(file, { header: true, complete: function(results) { processData(results.data); } }); } }); function processData(data) { // Extract relevant information from the data const dates = []; const prices = []; let volumes = []; // Investing.com CSV format typically has these columns data.forEach((row) => { // Check for the presence of these columns (adjust if needed based on your CSV format) if (row['تاريخ'] && row['سعر الاغلاق']) { dates.unshift(row['تاريخ']); prices.unshift(parseFloat(row['سعر الاغلاق'].replace(',', ''))); if (row['الحجم']) { volumes.unshift(parseInt(row['الحجم'].replace(',', ''))); } } else if (row['Date'] && row['Price']) { // English column names dates.unshift(row['Date']); prices.unshift(parseFloat(row['Price'].replace(',', ''))); if (row['Vol.']) { volumes.unshift(parseInt(row['Vol.'].replace(',', ''))); } } }); // Calculate indicators const ma20 = calculateMA(prices, 20); const ma50 = calculateMA(prices, 50); const ma200 = calculateMA(prices, 200); const rsiValues = calculateRSI(prices, 14); const macdValues = calculateMACD(prices); const volatility = calculateVolatility(prices, 20); // Display results resultsSection.style.display = 'block'; // Draw price chart drawPriceChart(dates, prices, ma20, ma50, ma200); // Draw indicators chart drawIndicatorsChart(dates, rsiValues, macdValues.macd, macdValues.signal); // Generate statistics displayStatistics(prices, volumes, volatility, rsiValues, macdValues); // Generate recommendations displayRecommendations(prices, ma20, ma50, ma200, rsiValues, macdValues); } function calculateMA(data, period) { const result = []; for (let i = 0; i < data.length; i++) { if (i < period - 1) { result.push(null); continue; } let sum = 0; for (let j = 0; j < period; j++) { sum += data[i - j]; } result.push(sum / period); } return result; } function calculateRSI(prices, period) { const rsi = []; const deltas = []; // Calculate price changes for (let i = 1; i < prices.length; i++) { deltas.push(prices[i] - prices[i - 1]); } // Initialize RSI values for (let i = 0; i < period; i++) { rsi.push(null); } // Calculate RSI for each window for (let i = period; i < deltas.length + 1; i++) { const windowDeltas = deltas.slice(i - period, i); let gains = 0; let losses = 0; windowDeltas.forEach(delta => { if (delta > 0) { gains += delta; } else { losses -= delta; } }); const avgGain = gains / period; const avgLoss = losses / period; let rs = 0; if (avgLoss !== 0) { rs = avgGain / avgLoss; } rsi.push(100 - (100 / (1 + rs))); } return rsi; } function calculateMACD(prices, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) { // Calculate EMAs const emaFast = calculateEMA(prices, fastPeriod); const emaSlow = calculateEMA(prices, slowPeriod); // Calculate MACD line const macdLine = []; for (let i = 0; i < prices.length; i++) { if (emaFast[i] !== null && emaSlow[i] !== null) { macdLine.push(emaFast[i] - emaSlow[i]); } else { macdLine.push(null); } } // Calculate signal line (9-day EMA of MACD line) const signalLine = calculateEMA(macdLine, signalPeriod); // Calculate histogram const histogram = []; for (let i = 0; i < macdLine.length; i++) { if (macdLine[i] !== null && signalLine[i] !== null) { histogram.push(macdLine[i] - signalLine[i]); } else { histogram.push(null); } } return { macd: macdLine, signal: signalLine, histogram: histogram }; } function calculateEMA(data, period) { const ema = []; const multiplier = 2 / (period + 1); // Initialize EMA with SMA let sma = 0; for (let i = 0; i < period; i++) { sma += data[i]; ema.push(null); } sma /= period; ema[period - 1] = sma; // Calculate EMA for remaining data for (let i = period; i < data.length; i++) { ema.push((data[i] - ema[i - 1]) * multiplier + ema[i - 1]); } return ema; } function calculateVolatility(prices, period) { if (prices.length < period) { return null; } const returns = []; for (let i = 1; i < prices.length; i++) { returns.push((prices[i] / prices[i - 1]) - 1); } const meanReturn = returns.reduce((a, b) => a + b, 0) / returns.length; const squaredDiffs = returns.map(r => Math.pow(r - meanReturn, 2)); const variance = squaredDiffs.reduce((a, b) => a + b, 0) / squaredDiffs.length; // Annualized volatility (assuming daily data) return Math.sqrt(variance) * Math.sqrt(252) * 100; } function drawPriceChart(dates, prices, ma20, ma50, ma200) { const ctx = document.getElementById('priceChart').getContext('2d'); if (priceChart) { priceChart.destroy(); } priceChart = new Chart(ctx, { type: 'line', data: { labels: dates, datasets: [ { label: 'السعر', data: prices, borderColor: 'rgba(44, 115, 210, 1)', backgroundColor: 'rgba(44, 115, 210, 0.1)', fill: true, tension: 0.1 }, { label: 'المتوسط المتحرك 20 يوم', data: ma20, borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 2, fill: false, tension: 0.1 }, { label: 'المتوسط المتحرك 50 يوم', data: ma50, borderColor: 'rgba(255, 159, 64, 1)', borderWidth: 2, fill: false, tension: 0.1 }, { label: 'المتوسط المتحرك 200 يوم', data: ma200, borderColor: 'rgba(255, 99, 132, 1)', borderWidth: 2, fill: false, tension: 0.1 } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { ticks: { maxTicksLimit: 10 } } }, interaction: { mode: 'index', intersect: false } } }); } function drawIndicatorsChart(dates, rsiValues, macdValues, signalValues) { const ctx = document.getElementById('indicatorsChart').getContext('2d'); if (indicatorsChart) { indicatorsChart.destroy(); } indicatorsChart = new Chart(ctx, { type: 'line', data: { labels: dates, datasets: [ { label: 'مؤشر القوة النسبية (RSI)', data: rsiValues, borderColor: 'rgba(153, 102, 255, 1)', backgroundColor: 'rgba(153, 102, 255, 0.2)', yAxisID: 'rsi', fill: true }, { label: 'MACD', data: macdValues, borderColor: 'rgba(54, 162, 235, 1)', backgroundColor: 'rgba(54, 162, 235, 0.2)', yAxisID: 'macd' }, { label: 'إشارة MACD', data: signalValues, borderColor: 'rgba(255, 99, 132, 1)', backgroundColor: 'rgba(255, 99, 132, 0.2)', yAxisID: 'macd' } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { ticks: { maxTicksLimit: 10 } }, rsi: { type: 'linear', position: 'left', min: 0, max: 100, grid: { drawOnChartArea: false }, title: { display: true, text: 'RSI' } }, macd: { type: 'linear', position: 'right', grid: { drawOnChartArea: false }, title: { display: true, text: 'MACD' } } }, interaction: { mode: 'index', intersect: false } } }); } function displayStatistics(prices, volumes, volatility, rsiValues, macdValues) { const statsContent = document.getElementById('statsContent'); // Filter out null values const filteredRSI = rsiValues.filter(val => val !== null); const filteredMACD = macdValues.macd.filter(val => val !== null); // Calculate statistics const currentPrice = prices[prices.length - 1]; const priceChange = prices[prices.length - 1] - prices[prices.length - 2]; const priceChangePercent = (priceChange / prices[prices.length - 2]) * 100; const lastRSI = filteredRSI[filteredRSI.length - 1]; const lastMACD = filteredMACD[filteredMACD.length - 1]; // Calculate 52-week high and low const yearPrices = prices.slice(-252); // Assuming 252 trading days in a year const high52Week = Math.max(...yearPrices); const low52Week = Math.min(...yearPrices); // Average volume (if available) let avgVolume = 'غير متوفر'; if (volumes.length > 0) { const monthVolumes = volumes.slice(-30); // Last 30 days avgVolume = Math.round(monthVolumes.reduce((a, b) => a + b, 0) / monthVolumes.length).toLocaleString(); } statsContent.innerHTML = `
السعر الحالي
${currentPrice.toFixed(2)}
التغير اليومي
${priceChange.toFixed(2)} (${priceChangePercent.toFixed(2)}%)
أعلى سعر (52 أسبوع)
${high52Week.toFixed(2)}
أدنى سعر (52 أسبوع)
${low52Week.toFixed(2)}
متوسط حجم التداول (30 يوم)
${avgVolume}
مؤشر القوة النسبية (RSI)
${lastRSI.toFixed(2)}
مؤشر MACD
<

إرسال تعليق

أحدث أقدم

نموذج الاتصال