@dendaio/n8n-nodes-collection
Version:
🚀 Comprehensive n8n node collection for financial analysis and automation. Features 55+ technical indicators (RSI, MACD, Bollinger Bands), 32+ candlestick patterns (Doji, Hammer, Engulfing), derivative statistics (Open Interest, Funding Rate, Long/Short
326 lines • 14.1 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TechnicalChart = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const puppeteer_1 = __importDefault(require("puppeteer"));
class TechnicalChart {
constructor() {
this.description = {
displayName: 'Technical Chart',
name: 'technicalChart',
icon: 'file:icon.svg',
group: ['transform'],
version: 1,
description: 'Generate technical charts using remote browser and save as images',
defaults: {
name: 'Technical Chart',
},
inputs: ["main"],
outputs: ["main"],
properties: [
{
displayName: 'Browser WebSocket Endpoint',
name: 'browserWSEndpoint',
type: 'string',
default: 'ws://localhost:3000',
description: 'WebSocket endpoint for the remote browser',
required: true,
noDataExpression: true,
},
{
displayName: 'TradingView Endpoint',
name: 'tradingviewEndpoint',
type: 'string',
default: 'https://www.tradingview.com/chart',
description: 'TradingView chart endpoint URL',
required: true,
noDataExpression: true,
},
{
displayName: 'Symbol',
name: 'symbol',
type: 'string',
default: 'BTC/USDT',
description: 'Trading pair symbol (e.g., BTC/USDT, ETH/USDT)',
required: true,
noDataExpression: true,
},
{
displayName: 'Timeframe',
name: 'timeframe',
type: 'options',
options: [
{ name: '1 Day', value: '1d' },
{ name: '1 Hour', value: '1h' },
{ name: '1 Minute', value: '1m' },
{ name: '1 Month', value: '1M' },
{ name: '1 Week', value: '1w' },
{ name: '12 Hours', value: '12h' },
{ name: '15 Minutes', value: '15m' },
{ name: '2 Hours', value: '2h' },
{ name: '30 Minutes', value: '30m' },
{ name: '4 Hours', value: '4h' },
{ name: '5 Minutes', value: '5m' },
{ name: '6 Hours', value: '6h' },
{ name: '8 Hours', value: '8h' },
],
default: '1h',
noDataExpression: true,
},
{
displayName: 'Theme',
name: 'theme',
type: 'options',
options: [
{ name: 'Light', value: 'light' },
{ name: 'Dark', value: 'dark' },
],
default: 'light',
noDataExpression: true,
},
{
displayName: 'Chart Width',
name: 'width',
type: 'number',
typeOptions: {
minValue: 800,
maxValue: 3840,
},
default: 1920,
description: 'Width of the chart in pixels',
noDataExpression: true,
},
{
displayName: 'Chart Height',
name: 'height',
type: 'number',
typeOptions: {
minValue: 600,
maxValue: 2160,
},
default: 1080,
description: 'Height of the chart in pixels',
noDataExpression: true,
},
{
displayName: 'Layout',
name: 'layout',
type: 'string',
default: '',
description: 'Chart layout identifier',
noDataExpression: true,
},
{
displayName: 'Study',
name: 'study',
type: 'string',
default: '',
description: 'Technical analysis study identifier',
noDataExpression: true,
},
{
displayName: 'Market',
name: 'market',
type: 'options',
options: [
{ name: 'Futures', value: 'futures' },
{ name: 'Spot', value: 'spot' },
],
default: 'futures',
description: 'Market type',
noDataExpression: true,
},
{
displayName: 'Output Options',
name: 'outputOptions',
type: 'collection',
placeholder: 'Add Output Option',
default: {},
options: [
{
displayName: 'Include Base64',
name: 'includeBase64',
type: 'boolean',
default: true,
description: 'Whether to include base64 data in the output',
},
{
displayName: 'Wait for Chart Load',
name: 'waitForChartLoad',
type: 'number',
typeOptions: {
minValue: 1000,
maxValue: 30000,
},
default: 5000,
description: 'Additional wait time in milliseconds for chart to fully load',
noDataExpression: true,
},
],
},
{
displayName: 'Advanced Options',
name: 'advancedOptions',
type: 'collection',
placeholder: 'Add Advanced Option',
default: {},
options: [
{
displayName: 'Ignore HTTPS Errors',
name: 'ignoreHttpsErrors',
type: 'boolean',
default: false,
description: 'Whether to ignore HTTPS errors',
},
{
displayName: 'Timeout',
name: 'timeout',
type: 'number',
typeOptions: {
minValue: 10000,
maxValue: 120000,
},
default: 30000,
description: 'Page load timeout in milliseconds',
noDataExpression: true,
},
{
displayName: 'User Agent',
name: 'userAgent',
type: 'string',
default: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
description: 'Custom user agent string',
noDataExpression: true,
},
],
},
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const browserWSEndpoint = this.getNodeParameter('browserWSEndpoint', i);
const tradingviewEndpoint = this.getNodeParameter('tradingviewEndpoint', i);
const symbol = this.getNodeParameter('symbol', i);
const timeframe = this.getNodeParameter('timeframe', i);
const theme = this.getNodeParameter('theme', i);
const width = this.getNodeParameter('width', i);
const height = this.getNodeParameter('height', i);
const layout = this.getNodeParameter('layout', i);
const study = this.getNodeParameter('study', i);
const market = this.getNodeParameter('market', i);
const outputOptions = this.getNodeParameter('outputOptions', i, {});
const advancedOptions = this.getNodeParameter('advancedOptions', i, {});
if (!browserWSEndpoint) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Browser WebSocket endpoint is required');
}
if (!tradingviewEndpoint) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'TradingView endpoint is required');
}
if (!symbol) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Symbol is required');
}
const includeBase64 = outputOptions.includeBase64 !== false;
const waitForChartLoad = outputOptions.waitForChartLoad || 5000;
const userAgent = advancedOptions.userAgent ||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
const timeout = advancedOptions.timeout || 30000;
const ignoreHttpsErrors = advancedOptions.ignoreHttpsErrors === true;
const browser = await puppeteer_1.default.connect({
browserWSEndpoint,
ignoreHTTPSErrors: ignoreHttpsErrors,
});
const page = await browser.newPage();
await page.setViewport({
width,
height,
deviceScaleFactor: 1,
isMobile: false,
});
await page.setUserAgent(userAgent);
await page.setExtraHTTPHeaders({
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
});
page.setDefaultTimeout(timeout);
page.setDefaultNavigationTimeout(timeout);
let chartUrl = `${tradingviewEndpoint}/?theme=${theme}&symbol=${symbol}&timeframe=${timeframe}`;
if (layout) {
chartUrl += `&layout=${encodeURIComponent(layout)}`;
}
if (study) {
chartUrl += `&study=${encodeURIComponent(study)}`;
}
if (market) {
chartUrl += `&market=${encodeURIComponent(market)}`;
}
const gotoOptions = {
waitUntil: ['domcontentloaded', 'networkidle2'],
timeout,
};
await page.goto(chartUrl, gotoOptions);
if (waitForChartLoad > 0) {
await new Promise((resolve) => setTimeout(resolve, waitForChartLoad));
}
const imageData = (await page.evaluate('saveChartToBase64()'));
if (!imageData) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Failed to get chart data from saveChartToBase64 function');
}
const base64Data = imageData.replace(/^data:image\/[^;]+;base64,/, '');
const outputData = {
success: true,
symbol,
timeframe,
theme,
layout,
study,
market,
chartUrl,
dimensions: {
width,
height,
},
chartImage: imageData,
timestamp: new Date().toISOString(),
metadata: {
browserWSEndpoint,
tradingviewEndpoint,
userAgent,
timeout,
ignoreHttpsErrors,
},
};
if (includeBase64) {
outputData.base64Data = base64Data;
}
await browser.close();
returnData.push({
json: outputData,
});
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
success: false,
error: error instanceof Error ? error.message : 'Unknown error occurred',
timestamp: new Date().toISOString(),
},
});
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.TechnicalChart = TechnicalChart;
//# sourceMappingURL=TechnicalChart.node.js.map