@neabyte/chart-to-image
Version:
Convert trading charts to images using Node.js canvas with advanced features: 6 chart types, VWAP/EMA/SMA indicators, custom colors, themes, hide elements, scaling, and PNG/JPEG export formats.
152 lines (151 loc) • 5.21 kB
JavaScript
export class ChartConfig {
symbol;
timeframe;
exchange;
outputPath;
width;
height;
theme;
chartType;
indicators;
watermark;
customBarColors;
horizontalLevels;
title;
showTitle;
showTimeAxis;
showGrid;
showVWAP;
showEMA;
emaPeriod;
showSMA;
smaPeriod;
showBollingerBands;
bbPeriod;
bbStandardDeviations;
bbColors;
backgroundColor;
textColor;
constructor(config) {
this.assignBasicProperties(config);
this.assignOptionalProperties(config);
this.validate();
}
assignBasicProperties(config) {
this.symbol = config.symbol || 'BTC/USDT';
this.timeframe = config.timeframe || '1h';
this.exchange = config.exchange || 'binance';
this.outputPath = config.outputPath || 'chart.png';
this.width = config.width || 1200;
this.height = config.height || 800;
this.theme = config.theme || 'dark';
this.chartType = config.chartType || 'candlestick';
this.indicators = config.indicators || [];
}
assignOptionalProperties(config) {
this.assignDisplayProperties(config);
this.assignIndicatorProperties(config);
this.assignStylingProperties(config);
}
assignDisplayProperties(config) {
if (config.customBarColors !== undefined) {
this.customBarColors = config.customBarColors;
}
if (config.horizontalLevels !== undefined) {
this.horizontalLevels = config.horizontalLevels;
}
if (config.title !== undefined) {
this.title = config.title;
}
if (config.showTitle !== undefined) {
this.showTitle = config.showTitle;
}
if (config.showTimeAxis !== undefined) {
this.showTimeAxis = config.showTimeAxis;
}
if (config.showGrid !== undefined) {
this.showGrid = config.showGrid;
}
if (config.watermark !== undefined) {
this.watermark = config.watermark;
}
}
assignIndicatorProperties(config) {
if (config.showVWAP !== undefined) {
this.showVWAP = config.showVWAP;
}
if (config.showEMA !== undefined) {
this.showEMA = config.showEMA;
}
if (config.emaPeriod !== undefined) {
this.emaPeriod = config.emaPeriod;
}
if (config.showSMA !== undefined) {
this.showSMA = config.showSMA;
}
if (config.smaPeriod !== undefined) {
this.smaPeriod = config.smaPeriod;
}
if (config.showBollingerBands !== undefined) {
this.showBollingerBands = config.showBollingerBands;
}
if (config.bbPeriod !== undefined) {
this.bbPeriod = config.bbPeriod;
}
if (config.bbStandardDeviations !== undefined) {
this.bbStandardDeviations = config.bbStandardDeviations;
}
if (config.bbColors !== undefined) {
this.bbColors = config.bbColors;
}
}
assignStylingProperties(config) {
if (config.backgroundColor !== undefined) {
this.backgroundColor = config.backgroundColor;
}
if (config.textColor !== undefined) {
this.textColor = config.textColor;
}
}
validate() {
if (!this.symbol || !this.symbol.includes('/')) {
throw new Error('Invalid symbol format. Use format: BASE/QUOTE (e.g., BTC/USDT)');
}
if (!this.isValidTimeframe(this.timeframe)) {
throw new Error(`Invalid timeframe: ${this.timeframe}`);
}
if (!this.isValidChartType(this.chartType)) {
throw new Error(`Invalid chart type: ${this.chartType}`);
}
if (this.width < 100 || this.height < 100) {
throw new Error('Chart dimensions must be at least 100x100 pixels');
}
if (!this.outputPath.match(/\.(png|jpg|jpeg|svg)$/i)) {
throw new Error('Output path must have a valid image extension (.png, .jpg, .jpeg, .svg)');
}
}
isValidTimeframe(timeframe) {
const validTimeframes = ['1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w'];
return validTimeframes.includes(timeframe);
}
isValidChartType(chartType) {
const validChartTypes = ['candlestick', 'line', 'area', 'heikin-ashi', 'renko', 'line-break'];
return validChartTypes.includes(chartType);
}
getChartOptions() {
return {
width: this.width,
height: this.height,
backgroundColor: this.theme === 'dark' ? '#1e222d' : '#ffffff',
textColor: this.theme === 'dark' ? '#ffffff' : '#000000',
gridColor: this.theme === 'dark' ? '#2b2b43' : '#e1e3e6',
borderColor: this.theme === 'dark' ? '#2b2b43' : '#e1e3e6',
...(this.watermark && { watermark: this.watermark }),
watermarkColor: this.theme === 'dark' ? '#ffffff' : '#000000',
watermarkOpacity: 0.3
};
}
toString() {
return `ChartConfig(${this.symbol}, ${this.timeframe}, ${this.width}x${this.height})`;
}
}