candlestick-chart-generator
Version:
A Node.js library for generating candlestick chart screenshots using financial data
96 lines (81 loc) • 3.54 kB
JavaScript
const yahooFinance = require('yahoo-finance2').default;
class DataFetcher {
constructor() {
// Suppress the deprecation notice for historical API
yahooFinance.suppressNotices(['ripHistorical']);
}
/**
* Fetch historical OHLC data for a given symbol and interval
* @param {string} symbol - The ticker symbol (e.g., 'AAPL', 'BTC-USD', 'EURUSD=X')
* @param {string} interval - The time interval ('1m', '1h', '1d', etc.)
* @param {string|Date} startDate - Start date for historical data
* @param {string|Date} endDate - End date for historical data
* @returns {Promise<Array>} Array of OHLC data formatted for Lightweight Charts
*/
async fetchHistoricalData(symbol, interval, startDate, endDate) {
try {
// Convert interval to yahoo-finance2 format
const yahooInterval = this._convertInterval(interval);
// Prepare query options for chart API
const queryOptions = {
period1: startDate ? new Date(startDate) : new Date(Date.now() - 365 * 24 * 60 * 60 * 1000), // Default to 1 year ago
period2: endDate ? new Date(endDate) : new Date(), // Default to now
interval: yahooInterval
};
// Use chart API instead of historical (which is deprecated)
const result = await yahooFinance.chart(symbol, queryOptions);
if (!result || !result.quotes || result.quotes.length === 0) {
throw new Error(`No data found for symbol: ${symbol}`);
}
// Transform data to Lightweight Charts format
return this._transformChartData(result.quotes);
} catch (error) {
throw new Error(`Failed to fetch data for ${symbol}: ${error.message}`);
}
}
/**
* Convert interval string to yahoo-finance2 format
* @param {string} interval - Input interval (e.g., '1m', '1h', '1d')
* @returns {string} Yahoo Finance interval format
*/
_convertInterval(interval) {
const intervalMap = {
'1m': '1m',
'2m': '2m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'60m': '60m',
'90m': '90m',
'1h': '1h',
'1d': '1d',
'5d': '5d',
'1wk': '1wk',
'1mo': '1mo',
'3mo': '3mo'
};
const yahooInterval = intervalMap[interval];
if (!yahooInterval) {
throw new Error(`Unsupported interval: ${interval}. Supported intervals: ${Object.keys(intervalMap).join(', ')}`);
}
return yahooInterval;
}
/**
* Transform Yahoo Finance chart data to Lightweight Charts format
* @param {Array} quotes - Raw quotes data from Yahoo Finance chart API
* @returns {Array} Transformed data for Lightweight Charts
*/
_transformChartData(quotes) {
return quotes
.filter(quote => quote.open !== null && quote.high !== null && quote.low !== null && quote.close !== null)
.map(quote => ({
time: Math.floor(quote.date.getTime() / 1000), // Convert to Unix timestamp
open: parseFloat(quote.open),
high: parseFloat(quote.high),
low: parseFloat(quote.low),
close: parseFloat(quote.close)
}))
.sort((a, b) => a.time - b.time); // Ensure chronological order
}
}
module.exports = DataFetcher;