maher-tradingview-api
Version:
Tradingview instant stocks API, indicator alerts, trading bot, and more !
269 lines (229 loc) • 9.8 kB
JavaScript
/**
* test-data-sources.js
* Test tool for multiple data sources
*/
// Test all data sources and display results
async function testAllDataSources(symbol = 'AAPL', timeframe = 'D') {
const results = {};
const errors = {};
console.log(`Starting to test all data sources for ${symbol} (${timeframe})...`);
// Array of available data sources
const sources = [
{ name: 'TradingView API', endpoint: `/api/chart-data?symbol=${symbol}&timeframe=${timeframe}` },
{ name: 'Alpha Vantage', endpoint: `/api/proxy/alphavantage?symbol=${symbol}&interval=${timeframe}` },
{ name: 'Yahoo Finance', endpoint: `/api/proxy/yahoo?symbol=${symbol}&interval=${timeframe === 'D' ? '1d' : (timeframe === 'W' ? '1wk' : '1mo')}` },
{ name: 'IEX Cloud', endpoint: `/api/proxy/iex?symbol=${symbol}&range=1y` },
{ name: 'Finnhub', endpoint: `/api/proxy/finnhub?symbol=${symbol}&resolution=${timeframe}` }
];
// Create results container
const resultsContainer = document.createElement('div');
resultsContainer.className = 'data-sources-test-results';
resultsContainer.style.cssText = 'margin: 20px; padding: 20px; border: 1px solid #ddd; border-radius: 5px;';
const heading = document.createElement('h2');
heading.textContent = 'Data Sources Test';
resultsContainer.appendChild(heading);
// Add test info
const info = document.createElement('p');
info.innerHTML = `<strong>Symbol:</strong> ${symbol} <strong>Timeframe:</strong> ${timeframe}`;
resultsContainer.appendChild(info);
// Create results table
const table = document.createElement('table');
table.style.cssText = 'width: 100%; border-collapse: collapse; margin-top: 20px;';
// Create table header
const thead = document.createElement('thead');
thead.innerHTML = `
<tr>
<th style="padding: 8px; border: 1px solid #ddd;">Source</th>
<th style="padding: 8px; border: 1px solid #ddd;">Status</th>
<th style="padding: 8px; border: 1px solid #ddd;">Response Time</th>
<th style="padding: 8px; border: 1px solid #ddd;">Data Points</th>
</tr>
`;
table.appendChild(thead);
// Create table body
const tbody = document.createElement('tbody');
table.appendChild(tbody);
// Add table to container
resultsContainer.appendChild(table);
// Add container to page
document.body.appendChild(resultsContainer);
// Test each data source
for (const source of sources) {
// Create table row
const row = document.createElement('tr');
row.innerHTML = `
<td style="padding: 8px; border: 1px solid #ddd;">${source.name}</td>
<td style="padding: 8px; border: 1px solid #ddd;"><span class="status">Testing...</span></td>
<td style="padding: 8px; border: 1px solid #ddd;" class="response-time">-</td>
<td style="padding: 8px; border: 1px solid #ddd;" class="data-points">-</td>
`;
tbody.appendChild(row);
const statusCell = row.querySelector('.status');
const responseTimeCell = row.querySelector('.response-time');
const dataPointsCell = row.querySelector('.data-points');
try {
console.log(`Testing data source: ${source.name}`);
// Record start time
const startTime = performance.now();
// Fetch data from source
const response = await fetch(source.endpoint);
const data = await response.json();
// Calculate response time
const endTime = performance.now();
const responseTime = Math.round(endTime - startTime);
// Process data based on source
let dataPoints = 0;
let formattedData = null;
if (source.name === 'TradingView API') {
if (data && data.data && Array.isArray(data.data)) {
formattedData = data.data;
dataPoints = data.data.length;
}
} else if (source.name === 'Alpha Vantage') {
const timeSeriesKey = Object.keys(data).find(key => key.includes('Time Series'));
if (timeSeriesKey && data[timeSeriesKey]) {
formattedData = Object.entries(data[timeSeriesKey]).map(([date, values]) => ({
time: date,
open: parseFloat(values['1. open']),
high: parseFloat(values['2. high']),
low: parseFloat(values['3. low']),
close: parseFloat(values['4. close']),
volume: parseFloat(values['5. volume'] || '0')
}));
dataPoints = formattedData.length;
}
} else if (source.name === 'Yahoo Finance') {
if (data && data.chart && data.chart.result && data.chart.result.length > 0) {
const result = data.chart.result[0];
const timestamps = result.timestamp || [];
const quotes = result.indicators.quote && result.indicators.quote[0] || {};
formattedData = timestamps.map((timestamp, i) => ({
time: new Date(timestamp * 1000).toISOString().split('T')[0],
open: quotes.open && quotes.open[i] || null,
high: quotes.high && quotes.high[i] || null,
low: quotes.low && quotes.low[i] || null,
close: quotes.close && quotes.close[i] || null,
volume: quotes.volume && quotes.volume[i] || 0
})).filter(item => item.open && item.close);
dataPoints = formattedData.length;
}
} else if (source.name === 'IEX Cloud') {
if (Array.isArray(data) && data.length > 0) {
formattedData = data.map(item => ({
time: item.date,
open: item.open,
high: item.high,
low: item.low,
close: item.close,
volume: item.volume
}));
dataPoints = formattedData.length;
}
} else if (source.name === 'Finnhub') {
if (data && data.s === 'ok' && data.t && data.t.length > 0) {
formattedData = data.t.map((timestamp, i) => ({
time: new Date(timestamp * 1000).toISOString().split('T')[0],
open: data.o && data.o[i] || null,
high: data.h && data.h[i] || null,
low: data.l && data.l[i] || null,
close: data.c && data.c[i] || null,
volume: data.v && data.v[i] || 0
}));
dataPoints = formattedData.length;
}
}
// Store results
results[source.name] = {
responseTime,
dataPoints,
data: formattedData
};
// Update table
statusCell.textContent = 'Success';
statusCell.style.color = '#22ab94';
responseTimeCell.textContent = `${responseTime}ms`;
dataPointsCell.textContent = dataPoints;
console.log(`${source.name} test successful: ${dataPoints} data points in ${responseTime}ms`);
} catch (error) {
console.error(`${source.name} test failed:`, error);
// Store error
errors[source.name] = error.message || 'Unknown error';
// Update table
statusCell.textContent = 'Failed';
statusCell.style.color = '#f23645';
responseTimeCell.textContent = '-';
dataPointsCell.textContent = '-';
// Add error details
const errorRow = document.createElement('tr');
errorRow.innerHTML = `
<td colspan="4" style="padding: 8px; border: 1px solid #ddd; background-color: #fff3cd;">
<details>
<summary style="color: #f23645; cursor: pointer;">Error Details</summary>
<p style="margin-top: 5px;">${error.message || 'Unknown error'}</p>
</details>
</td>
`;
row.insertAdjacentElement('afterend', errorRow);
}
}
return { results, errors };
}
// Create test button
function createTestButton() {
const button = document.createElement('button');
button.textContent = 'Test All Data Sources';
button.className = 'data-source-test-button';
button.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
background-color: #0088cc;
color: white;
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
z-index: 1000;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
`;
// Add click handler
button.addEventListener('click', async () => {
let symbol = 'AAPL'; // Default value
// Try to get symbol from URL or global variables
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('symbol')) {
symbol = urlParams.get('symbol');
} else if (window.currentSymbol) {
symbol = window.currentSymbol;
}
// Get timeframe
let timeframe = 'D'; // Default value
if (urlParams.has('timeframe')) {
timeframe = urlParams.get('timeframe');
} else if (window.currentTimeframe) {
timeframe = window.currentTimeframe;
}
// Change button text
button.textContent = 'Testing Sources...';
button.disabled = true;
try {
// Test all sources
await testAllDataSources(symbol, timeframe);
// Reset button
button.textContent = 'Test All Data Sources';
button.disabled = false;
} catch (error) {
console.error('Error testing sources:', error);
button.textContent = 'Test Failed. Try Again?';
button.disabled = false;
}
});
// Add button to page
document.body.appendChild(button);
}
// Run on page load
document.addEventListener('DOMContentLoaded', () => {
// Create test button
createTestButton();
console.log('Data sources test tool loaded');
});