maher-tradingview-api
Version:
Tradingview instant stocks API, indicator alerts, trading bot, and more !
466 lines (396 loc) • 18.5 kB
JavaScript
/* 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 */
/**
* chart-initializer.js
* ملف مساعد لبدء تشغيل وتهيئة جميع الرسوم البيانية
*/
// متغيرات عامة لاستخدامها في جميع وظائف الرسوم البيانية
let candleData = null;
let chartReadyStatus = false;
// وظيفة للتهيئة العامة للرسوم البيانية - يتم استدعاؤها من الخارج
function initializeCharts(symbol, data) {
console.log('تهيئة الرسوم البيانية...');
// التأكد من وجود الملفات المساعدة
if (window.ChartUtils && typeof window.ChartUtils.ensureReadyForCharts === 'function') {
// استخدام الملف المساعد للتحقق من الجاهزية
window.ChartUtils.ensureReadyForCharts(function() {
initializeChartsWithData(symbol, data);
});
} else {
// طريقة بديلة في حالة عدم وجود الملف المساعد
console.warn('ملف أدوات الرسوم البيانية المساعدة غير موجود. استخدام الطريقة البديلة...');
initializeChartsWithData(symbol, data);
}
}
// وظيفة لتهيئة الرسوم البيانية ببيانات محددة
function initializeChartsWithData(symbol, data) {
console.log('تهيئة الرسوم البيانية بالبيانات المقدمة...');
try {
// تحقق من البيانات
if (!data || !Array.isArray(data) || data.length === 0) {
console.error('البيانات غير صالحة للرسم البياني:', data);
showChartError('priceChart', 'البيانات غير صالحة للرسم البياني');
return;
}
// تخزين البيانات في متغير عام للاستخدام لاحقاً
candleData = data;
console.log(`تم تحميل ${candleData.length} شمعة يابانية للرسم البياني`);
// تجهيز بيانات الرسم البياني الرئيسي
const chartData = {
symbol: symbol,
labels: processLabels(data),
values: processValues(data)
};
// رسم الرسم البياني الرئيسي
console.log('رسم الرسم البياني الرئيسي...');
if (window.ChartRenderer && typeof window.ChartRenderer.renderPriceChart === 'function') {
window.ChartRenderer.renderPriceChart('priceChart', chartData.labels, chartData.values, chartData.symbol);
// تعيين الحالة على جاهز
chartReadyStatus = true;
// التحقق من المؤشرات الفنية بعد فترة قصيرة
setTimeout(checkChartsStatus, 1500);
} else {
console.error('وظيفة renderPriceChart غير موجودة!');
showChartError('priceChart', 'تعذر رسم المخطط البياني - مكتبة الرسم غير متوفرة');
}
} catch (error) {
console.error('حدث خطأ أثناء تهيئة الرسم البياني:', error);
showChartError('priceChart', 'حدث خطأ أثناء تهيئة الرسم البياني');
}
}
// معالجة تسميات المخطط
function processLabels(data) {
return data.map(candle => {
if (typeof candle.time === 'string') {
return candle.time.split(',')[0];
}
return candle.time || '';
});
}
// معالجة قيم المخطط
function processValues(data) {
return data.map(candle => {
const closePrice = parseFloat(candle.close);
if (isNaN(closePrice)) {
console.warn('قيمة غير صالحة في بيانات الشمعة:', candle);
return 0;
}
return closePrice;
});
}
// وظيفة لإظهار رسالة خطأ على عنصر canvas
function showChartError(chartId, errorMessage) {
const canvas = document.getElementById(chartId);
if (!canvas) return;
const ctx = canvas.getContext('2d');
// تنظيف الـ canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// رسم خلفية بيضاء
ctx.fillStyle = '#f8f8f8';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// رسم رسالة الخطأ
ctx.fillStyle = '#e74c3c';
ctx.font = '14px Arial';
ctx.textAlign = 'center';
ctx.fillText(errorMessage, canvas.width / 2, canvas.height / 2);
// إضافة رسالة لإعادة التحميل
ctx.fillStyle = '#666';
ctx.font = '12px Arial';
ctx.fillText('يرجى تحديث الصفحة للمحاولة مرة أخرى', canvas.width / 2, canvas.height / 2 + 30);
// إضافة حدود حمراء للـ canvas parent
const container = canvas.parentElement;
if (container) {
container.style.border = '2px solid #e74c3c';
container.style.borderRadius = '4px';
}
}
// وظيفة للتحقق من الرسوم البيانية
function checkChartsStatus() {
if (!chartReadyStatus || !Array.isArray(candleData)) return;
const chartIds = ['priceChart', 'maChart', 'bbChart', 'rsiChart', 'macdChart', 'volumeChart'];
// استخدام الأداة المساعدة إذا كانت متوفرة
if (window.ChartUtils && typeof window.ChartUtils.retryFailedCharts === 'function') {
window.ChartUtils.retryFailedCharts(chartIds, candleData);
} else {
// طريقة احتياطية في حالة عدم توفر الأداة المساعدة
checkChartsManually(chartIds);
}
}
// وظيفة للتحقق اليدوي من الرسوم البيانية
function checkChartsManually(chartIds) {
chartIds.forEach(function(id) {
const canvas = document.getElementById(id);
if (!canvas) return;
try {
const ctx = canvas.getContext('2d');
const chart = Chart.getChart(canvas);
// تحقق مما إذا كان الرسم البياني موجوداً ويحتوي على بيانات
if (!chart || !chart.data || !chart.data.datasets || chart.data.datasets.length === 0) {
console.warn(`الرسم البياني ${id} فارغ أو لم يتم تهيئته بشكل صحيح`);
// للرسم البياني الرئيسي، نقوم بإعادة تهيئته
if (id === 'priceChart' && candleData) {
const chartData = {
labels: processLabels(candleData),
values: processValues(candleData)
};
if (window.ChartRenderer && typeof window.ChartRenderer.renderPriceChart === 'function') {
setTimeout(() => {
window.ChartRenderer.renderPriceChart(id, chartData.labels, chartData.values, '');
}, 500);
}
}
}
} catch (error) {
console.error(`خطأ أثناء التحقق من الرسم البياني ${id}:`, error);
}
});
}
// وظيفة لإعداد المؤشرات الفنية
function setupTechnicalCharts(data) {
if (!data || !Array.isArray(data) || data.length === 0) {
console.warn('لا توجد بيانات لرسم المؤشرات الفنية');
return;
}
try {
console.log('إعداد المؤشرات الفنية...');
// التأكد من وجود وظائف المؤشرات الفنية
if (!window.TechnicalIndicators) {
console.error('مكتبة المؤشرات الفنية غير موجودة!');
return;
}
// رسم المؤشرات الفنية
renderIndicator('maChart', data, (id, data) => {
window.TechnicalIndicators.renderMAChart(id, data, [20, 50, 200]);
});
renderIndicator('bbChart', data, (id, data) => {
window.TechnicalIndicators.renderBollingerBandsChart(id, data, 20, 2);
});
renderIndicator('rsiChart', data, (id, data) => {
try {
const rsiValues = window.TechnicalIndicators.calculateRSI(data, 14);
if (rsiValues && rsiValues.length > 0) {
const lastRSI = rsiValues[rsiValues.length - 1].toFixed(2);
// تحديث قيمة RSI على الواجهة
const rsiValueElement = document.getElementById('rsiValue');
if (rsiValueElement) {
const rsiColor = lastRSI > 70 ? '#f23645' : (lastRSI < 30 ? '#22ab94' : '#666');
rsiValueElement.textContent = lastRSI;
rsiValueElement.style.color = rsiColor;
}
}
window.TechnicalIndicators.renderRSIChart(id, data, 14);
} catch (error) {
console.error('خطأ في رسم مؤشر RSI:', error);
}
});
renderIndicator('macdChart', data, (id, data) => {
try {
const macdData = window.TechnicalIndicators.calculateMACD(data);
if (macdData && macdData.macdLine && macdData.macdLine.length > 0) {
const lastMacdValue = macdData.macdLine[macdData.macdLine.length - 1].toFixed(2);
const lastSignalValue = macdData.signalLine[macdData.signalLine.length - 1].toFixed(2);
// تحديث قيم MACD على الواجهة
const macdValueElement = document.getElementById('macdValue');
if (macdValueElement) {
const macdColor = lastMacdValue > lastSignalValue ? '#22ab94' : '#f23645';
macdValueElement.textContent = `${lastMacdValue} (إشارة: ${lastSignalValue})`;
macdValueElement.style.color = macdColor;
}
}
window.TechnicalIndicators.renderMACDChart(id, data, 12, 26, 9);
} catch (error) {
console.error('خطأ في رسم مؤشر MACD:', error);
}
});
} catch (error) {
console.error('خطأ عام في إعداد المؤشرات الفنية:', error);
}
}
// وظيفة مساعدة لرسم المؤشر مع التعامل مع الأخطاء
function renderIndicator(chartId, data, renderFunction) {
if (!document.getElementById(chartId)) {
return;
}
try {
renderFunction(chartId, data);
} catch (error) {
console.error(`خطأ في رسم المؤشر ${chartId}:`, error);
showChartError(chartId, `تعذر رسم مؤشر ${chartId}`);
}
}
/**
* جلب وعرض بيانات الرسم البياني باستخدام مصدر البيانات النشط
* @param {string} symbol - رمز السهم
* @param {string} timeframe - الإطار الزمني
* @return {Promise<boolean>} نجاح أو فشل عملية جلب البيانات
*/
async function fetchAndRenderChart(symbol, timeframe) {
// عرض مؤشر التحميل
showLoading();
try {
let data = null;
// التحقق من وجود مدير مصادر البيانات
if (window.DataSourcesManager) {
const currentSource = window.DataSourcesManager.getCurrentSource();
switch (currentSource) {
case 'tradingview':
// استخدام TradingView API (الطريقة الأساسية)
if (typeof fetchChartData === 'function') {
data = await fetchChartData(symbol, timeframe);
}
break;
case 'alphavantage':
// استخدام Alpha Vantage
if (typeof window.DataSourcesManager.fetchAlphaVantageData === 'function') {
data = await window.DataSourcesManager.fetchAlphaVantageData(symbol, timeframe);
}
break;
case 'yahoo':
// استخدام Yahoo Finance
if (typeof window.DataSourcesManager.fetchYahooData === 'function') {
data = await window.DataSourcesManager.fetchYahooData(symbol, timeframe);
}
break;
case 'iex':
// استخدام IEX Cloud
if (typeof window.DataSourcesManager.fetchIEXData === 'function') {
data = await window.DataSourcesManager.fetchIEXData(symbol, timeframe);
}
break;
case 'finnhub':
// استخدام Finnhub
if (typeof window.DataSourcesManager.fetchFinnhubData === 'function') {
data = await window.DataSourcesManager.fetchFinnhubData(symbol, timeframe);
}
break;
default:
console.error(`مصدر بيانات غير معروف: ${currentSource}`);
// محاولة استخدام المصدر الأساسي
if (typeof fetchChartData === 'function') {
data = await fetchChartData(symbol, timeframe);
}
}
} else {
// إذا لم يكن مدير مصادر البيانات متاحًا، استخدم الطريقة الأساسية
if (typeof fetchChartData === 'function') {
data = await fetchChartData(symbol, timeframe);
}
}
// التحقق من البيانات
if (!data || !Array.isArray(data) || data.length === 0) {
console.error('لم يتم جلب بيانات صالحة من المصدر الحالي');
// محاولة استخدام مصدر بديل
if (window.DataSourcesManager && window.DataSourcesManager.handleSourceFailure) {
const currentSource = window.DataSourcesManager.getCurrentSource();
window.DataSourcesManager.handleSourceFailure(currentSource, new Error('بيانات غير صالحة'));
// إعادة المحاولة باستخدام المصدر الجديد
return fetchAndRenderChart(symbol, timeframe);
}
// إخفاء مؤشر التحميل وعرض رسالة خطأ
hideLoading();
if (typeof showLoadingError === 'function') {
showLoadingError('خطأ في جلب البيانات', 'فشل في الحصول على بيانات صالحة من المصدر الحالي. يرجى تحديث الصفحة أو محاولة مصدر بديل.', true);
}
return false;
}
// حفظ البيانات للاستخدام اللاحق
window.candleData = data;
// إرسال حدث تحميل البيانات
if (typeof dispatchChartDataLoaded === 'function') {
dispatchChartDataLoaded(symbol, data);
}
// عرض الرسم البياني
if (typeof renderCharts === 'function') {
renderCharts(data);
} else if (typeof ChartRenderer !== 'undefined') {
const labels = data.map(candle => typeof candle.time === 'string' ? candle.time.split(',')[0] : candle.time);
const values = data.map(candle => parseFloat(candle.close));
ChartRenderer.renderPriceChart('priceChart', labels, values, symbol);
}
// إعادة ضبط عداد الأخطاء للمصدر الحالي
if (window.DataSourcesManager && window.DataSourcesManager.resetFailureCount) {
window.DataSourcesManager.resetFailureCount();
}
// إخفاء أي رسائل خطأ سابقة
if (typeof hideLoadingError === 'function') {
hideLoadingError();
}
// إخفاء مؤشر التحميل
hideLoading();
return true;
} catch (error) {
console.error('خطأ في جلب وعرض البيانات:', error);
// محاولة استخدام مصدر بديل
if (window.DataSourcesManager && window.DataSourcesManager.handleSourceFailure) {
const currentSource = window.DataSourcesManager.getCurrentSource();
window.DataSourcesManager.handleSourceFailure(currentSource, error);
// إعادة المحاولة باستخدام المصدر الجديد
return fetchAndRenderChart(symbol, timeframe);
}
// إخفاء مؤشر التحميل وعرض رسالة خطأ
hideLoading();
if (typeof showLoadingError === 'function') {
showLoadingError('خطأ في جلب البيانات', 'حدث خطأ أثناء جلب البيانات. يرجى تحديث الصفحة أو محاولة مصدر بديل.', true);
}
return false;
}
}
/**
* عرض مؤشر التحميل
*/
function showLoading() {
const loadingOverlay = document.getElementById('loadingOverlay');
if (loadingOverlay) {
loadingOverlay.style.display = 'flex';
} else {
// إنشاء مؤشر التحميل إذا لم يكن موجودًا
const overlay = document.createElement('div');
overlay.id = 'loadingOverlay';
overlay.className = 'loading-overlay';
overlay.innerHTML = '<div class="loading-spinner"></div><div class="loading-text">جاري تحميل البيانات...</div>';
// تنسيق مؤشر التحميل
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.background = 'rgba(255, 255, 255, 0.8)';
overlay.style.display = 'flex';
overlay.style.flexDirection = 'column';
overlay.style.justifyContent = 'center';
overlay.style.alignItems = 'center';
overlay.style.zIndex = '9999';
document.body.appendChild(overlay);
}
}
/**
* إخفاء مؤشر التحميل
*/
function hideLoading() {
const loadingOverlay = document.getElementById('loadingOverlay');
if (loadingOverlay) {
loadingOverlay.style.display = 'none';
}
}
// تصدير الوظائف للاستخدام العام
window.ChartInitializer = {
initializeCharts: initializeCharts,
setupTechnicalCharts: setupTechnicalCharts,
checkChartsStatus: checkChartsStatus
};