Binance-Technische-Indikatoren-Webhook-Tool
Dies ist ein Finance, AI-Bereich Automatisierungsworkflow mit 69 Nodes. Hauptsächlich werden Code, Merge, Webhook, HttpRequest, RespondToWebhook und andere Nodes verwendet, kombiniert mit KI-Technologie für intelligente Automatisierung. Binance technischer Indikator Webhook-Tool
- •HTTP Webhook-Endpunkt (wird von n8n automatisch generiert)
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
Verwendete Nodes (69)
Kategorie
{
"id": "HrTD222kWpvKsy2j",
"meta": {
"instanceId": "a5283507e1917a33cc3ae615b2e7d5ad2c1e50955e6f831272ddd5ab816f3fb6"
},
"name": "Binance SM Indicators Webhook Tool",
"tags": [],
"nodes": [
{
"id": "61cb3bd7-60ba-4dcf-a080-146b7612a99b",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1080,
0
],
"parameters": {
"url": "https://api.binance.com/api/v3/klines",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "symbol",
"value": "={{$json.body.symbol}}"
},
{
"name": "interval",
"value": "15m"
},
{
"name": "limit",
"value": "40"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "b372f57e-917a-42d2-964c-25a296ea982d",
"name": "Webhook 15m Indikatoren",
"type": "n8n-nodes-base.webhook",
"position": [
-1460,
0
],
"webhookId": "39cc366c-af5f-472a-9d48-bbe30a4fe3ea",
"parameters": {
"path": "39cc366c-af5f-472a-9d48-bbe30a4fe3ea",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "46b937d5-7338-457f-b2f0-eb85ac44a8bb",
"name": "In 1 Array zusammenführen",
"type": "n8n-nodes-base.code",
"position": [
-740,
0
],
"parameters": {
"jsCode": "const klines = $input.all().map(item => item.json);\nreturn [{ json: { klines } }];"
},
"typeVersion": 2
},
{
"id": "5b8c1049-bcf4-41d4-bba3-5f76e940bd3e",
"name": "Bollinger Bands berechnen",
"type": "n8n-nodes-base.code",
"position": [
-280,
-460
],
"parameters": {
"jsCode": "// Get raw klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20;\nconst stdMultiplier = 2;\n\n// Validate type\nif (!Array.isArray(klines)) {\n throw new Error(\"klines is not an array\");\n}\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Ensure enough data\nif (closes.length < period) {\n throw new Error(`Not enough data: got ${closes.length}, expected at least ${period}`);\n}\n\n// BB calculation logic\nfunction calculateBB(prices, period) {\n const result = [];\n for (let i = period - 1; i < prices.length; i++) {\n const slice = prices.slice(i - period + 1, i + 1);\n const mean = slice.reduce((sum, val) => sum + val, 0) / period;\n const variance = slice.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / period;\n const stdDev = Math.sqrt(variance);\n\n result.push({\n close: prices[i],\n basis: mean,\n upper: mean + stdMultiplier * stdDev,\n lower: mean - stdMultiplier * stdDev,\n timestamp: klines[i][0]\n });\n }\n return result;\n}\n\n// Calculate bands\nconst bands = calculateBB(closes, period);\n\n// Format output\nreturn bands.map(b => ({\n json: {\n timestamp: b.timestamp,\n close: b.close,\n bb_basis: b.basis,\n bb_upper: b.upper,\n bb_lower: b.lower\n }\n}));"
},
"typeVersion": 2
},
{
"id": "b0391e28-03a3-40f0-8182-72df0928ca2c",
"name": "RSI berechnen",
"type": "n8n-nodes-base.code",
"position": [
-280,
-240
],
"parameters": {
"jsCode": "// Pull klines array from JSON\nconst klines = $input.first().json.klines;\n\n// === CONFIGURATION ===\nconst period = 14; // RSI period\n\n// === Extract closing prices ===\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// === Ensure enough data ===\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for RSI. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// === RSI Calculation ===\nfunction calculateRSI(prices, period) {\n const result = [];\n\n for (let i = period; i < prices.length; i++) {\n let gains = 0;\n let losses = 0;\n\n for (let j = i - period + 1; j <= i; j++) {\n const change = prices[j] - prices[j - 1];\n if (change >= 0) gains += change;\n else losses -= change;\n }\n\n const avgGain = gains / period;\n const avgLoss = losses / period;\n\n const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n const rsi = avgLoss === 0 ? 100 : 100 - (100 / (1 + rs));\n\n result.push({\n timestamp: klines[i][0],\n close: prices[i],\n rsi: rsi\n });\n }\n\n return result;\n}\n\n// === Run RSI ===\nconst rsiSeries = calculateRSI(closes, period);\n\n// === Return formatted RSI output ===\nreturn rsiSeries.map(r => ({\n json: {\n timestamp: r.timestamp,\n close: r.close,\n rsi: r.rsi\n }\n}));"
},
"typeVersion": 2
},
{
"id": "2c598960-630c-4687-91c0-bfae10da1943",
"name": "MACD berechnen",
"type": "n8n-nodes-base.code",
"position": [
-280,
-40
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Parameters\nconst fastPeriod = 12;\nconst slowPeriod = 26;\nconst signalPeriod = 9;\n\n// Validate data length\nconst minRequired = slowPeriod + signalPeriod;\nif (closes.length < minRequired) {\n throw new Error(`Not enough data for MACD. Need at least ${minRequired}, got ${closes.length}`);\n}\n\n// === Helper: EMA function ===\nfunction calculateEMA(prices, period) {\n const k = 2 / (period + 1);\n const ema = [prices.slice(0, period).reduce((a, b) => a + b, 0) / period];\n\n for (let i = period; i < prices.length; i++) {\n ema.push(prices[i] * k + ema[ema.length - 1] * (1 - k));\n }\n\n return ema;\n}\n\n// === MACD Core Calculation ===\nconst slowEMA = calculateEMA(closes, slowPeriod);\nconst fastEMA = calculateEMA(closes.slice(slowPeriod - fastPeriod), fastPeriod);\n\n// Align lengths\nconst alignedFastEMA = fastEMA.slice(fastEMA.length - slowEMA.length);\nconst macdLine = alignedFastEMA.map((val, i) => val - slowEMA[i]);\n\n// Signal line\nconst signalLine = calculateEMA(macdLine, signalPeriod);\n\n// Histogram\nconst histogram = macdLine.slice(signalPeriod - 1).map((macd, i) => macd - signalLine[i]);\n\n// Final output start index\nconst startIndex = closes.length - histogram.length;\n\nconst result = [];\n\nfor (let i = 0; i < histogram.length; i++) {\n const idx = startIndex + i;\n result.push({\n timestamp: klines[idx]?.[0] || null,\n close: closes[idx],\n macd: macdLine[i + signalPeriod - 1],\n signal: signalLine[i],\n histogram: histogram[i]\n });\n}\n\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "c50f7fa5-2707-47a4-9b32-1d582bf5d600",
"name": "SMA berechnen",
"type": "n8n-nodes-base.code",
"position": [
-280,
200
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 50, 100, 200, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute SMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// Calculate SMA values\nconst result = [];\n\nfor (let i = period - 1; i < closes.length; i++) {\n const slice = closes.slice(i - period + 1, i + 1);\n const sum = slice.reduce((a, b) => a + b, 0);\n const average = sum / period;\n\n result.push({\n timestamp: klines[i][0],\n close: closes[i],\n sma: average\n });\n}\n\n// Return formatted output\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "25ef2964-c9b1-4b9e-b6ce-3766b215d163",
"name": "EMA berechnen",
"type": "n8n-nodes-base.code",
"position": [
-280,
420
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 9, 12, 26, 50, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute EMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// EMA Calculation\nconst k = 2 / (period + 1);\nconst ema = [];\n\n// Start with SMA of first period\nlet sma = closes.slice(0, period).reduce((a, b) => a + b, 0) / period;\nema.push({\n timestamp: klines[period - 1][0],\n close: closes[period - 1],\n ema: sma\n});\n\n// Continue EMA calculation\nfor (let i = period; i < closes.length; i++) {\n const value = closes[i] * k + ema[ema.length - 1].ema * (1 - k);\n ema.push({\n timestamp: klines[i][0],\n close: closes[i],\n ema: value\n });\n}\n\n// Return result\nreturn ema.map(e => ({\n json: e\n}));"
},
"typeVersion": 2
},
{
"id": "df6546be-3778-4fba-801a-870c0fe883c3",
"name": "ADX berechnen",
"type": "n8n-nodes-base.code",
"position": [
-280,
660
],
"parameters": {
"jsCode": "// Get kline array from merged item\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 14;\n\n// Parse high, low, close arrays\nconst highs = klines.map(k => parseFloat(k[2]));\nconst lows = klines.map(k => parseFloat(k[3]));\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Validation\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for ADX. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// Initialize arrays\nconst tr = [];\nconst plusDM = [];\nconst minusDM = [];\n\n// Step 1: Calculate TR, +DM, -DM\nfor (let i = 1; i < klines.length; i++) {\n const highDiff = highs[i] - highs[i - 1];\n const lowDiff = lows[i - 1] - lows[i];\n const upMove = highDiff > 0 && highDiff > lowDiff ? highDiff : 0;\n const downMove = lowDiff > 0 && lowDiff > highDiff ? lowDiff : 0;\n\n const trueRange = Math.max(\n highs[i] - lows[i],\n Math.abs(highs[i] - closes[i - 1]),\n Math.abs(lows[i] - closes[i - 1])\n );\n\n tr.push(trueRange);\n plusDM.push(upMove);\n minusDM.push(downMove);\n}\n\n// Step 2: Smooth TR, +DM, -DM and calculate DI\nconst smoothedTR = [tr.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedPlusDM = [plusDM.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedMinusDM = [minusDM.slice(0, period).reduce((a, b) => a + b, 0)];\n\nfor (let i = period; i < tr.length; i++) {\n smoothedTR.push(smoothedTR[smoothedTR.length - 1] - smoothedTR[smoothedTR.length - 1] / period + tr[i]);\n smoothedPlusDM.push(smoothedPlusDM[smoothedPlusDM.length - 1] - smoothedPlusDM[smoothedPlusDM.length - 1] / period + plusDM[i]);\n smoothedMinusDM.push(smoothedMinusDM[smoothedMinusDM.length - 1] - smoothedMinusDM[smoothedMinusDM.length - 1] / period + minusDM[i]);\n}\n\nconst plusDI = smoothedPlusDM.map((val, i) => 100 * val / smoothedTR[i]);\nconst minusDI = smoothedMinusDM.map((val, i) => 100 * val / smoothedTR[i]);\n\n// Step 3: Calculate DX\nconst dx = plusDI.map((val, i) => {\n const diff = Math.abs(plusDI[i] - minusDI[i]);\n const sum = plusDI[i] + minusDI[i];\n return sum === 0 ? 0 : 100 * (diff / sum);\n});\n\n// Step 4: Smooth DX into ADX\nconst adx = [];\nconst firstADX = dx.slice(0, period).reduce((a, b) => a + b, 0) / period;\nadx.push(firstADX);\n\nfor (let i = period; i < dx.length; i++) {\n const newADX = (adx[adx.length - 1] * (period - 1) + dx[i]) / period;\n adx.push(newADX);\n}\n\n// Step 5: Final result formatting\nconst output = [];\n\nfor (let i = 0; i < adx.length; i++) {\n const index = i + (2 * period); // account for offset\n if (klines[index]) {\n output.push({\n timestamp: klines[index][0],\n close: closes[index],\n adx: adx[i],\n plusDI: plusDI[i + period],\n minusDI: minusDI[i + period]\n });\n }\n}\n\nreturn output.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "5ea4756f-a20a-444c-8471-57d209457823",
"name": "15 Min. Indikatoren zusammenführen",
"type": "n8n-nodes-base.merge",
"position": [
180,
-80
],
"parameters": {
"numberInputs": 6
},
"typeVersion": 3.1
},
{
"id": "0a46ea7c-a85d-4fc6-b20c-7e65ab962ea6",
"name": "Auf 15m Webhook antworten",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
560,
-20
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.3
},
{
"id": "40fcbba9-489b-4452-baf8-9a41ef0f9b07",
"name": "Webhook 1h Indikatoren",
"type": "n8n-nodes-base.webhook",
"position": [
-3220,
1760
],
"webhookId": "78948764-5cdb-4808-8ef9-2155f10dd721",
"parameters": {
"path": "78948764-5cdb-4808-8ef9-2155f10dd721",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "39e6b058-d800-4751-b75b-5e62be379c61",
"name": "Auf 1h Webhook antworten",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-1060,
1740
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.3
},
{
"id": "af471a36-1107-4ccd-be14-efa06ba27330",
"name": "1h Indikatoren zusammenführen",
"type": "n8n-nodes-base.merge",
"position": [
-1460,
1680
],
"parameters": {
"numberInputs": 6
},
"typeVersion": 3.1
},
{
"id": "d7d9bb31-6986-42e6-9f0c-7d7f00d66ee1",
"name": "In 1 Array 1h zusammenführen",
"type": "n8n-nodes-base.code",
"position": [
-2540,
1760
],
"parameters": {
"jsCode": "const klines = $input.all().map(item => item.json);\nreturn [{ json: { klines } }];"
},
"typeVersion": 2
},
{
"id": "a2e9d933-47d7-47f5-8d49-224860d8600a",
"name": "Bollinger Bands (1h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-2060,
1220
],
"parameters": {
"jsCode": "// Get raw klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20;\nconst stdMultiplier = 2;\n\n// Validate type\nif (!Array.isArray(klines)) {\n throw new Error(\"klines is not an array\");\n}\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Ensure enough data\nif (closes.length < period) {\n throw new Error(`Not enough data: got ${closes.length}, expected at least ${period}`);\n}\n\n// BB calculation logic\nfunction calculateBB(prices, period) {\n const result = [];\n for (let i = period - 1; i < prices.length; i++) {\n const slice = prices.slice(i - period + 1, i + 1);\n const mean = slice.reduce((sum, val) => sum + val, 0) / period;\n const variance = slice.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / period;\n const stdDev = Math.sqrt(variance);\n\n result.push({\n close: prices[i],\n basis: mean,\n upper: mean + stdMultiplier * stdDev,\n lower: mean - stdMultiplier * stdDev,\n timestamp: klines[i][0]\n });\n }\n return result;\n}\n\n// Calculate bands\nconst bands = calculateBB(closes, period);\n\n// Format output\nreturn bands.map(b => ({\n json: {\n timestamp: b.timestamp,\n close: b.close,\n bb_basis: b.basis,\n bb_upper: b.upper,\n bb_lower: b.lower\n }\n}));"
},
"typeVersion": 2
},
{
"id": "702e8bc8-d8f0-4fb4-b44f-fd19479c8b03",
"name": "RSI (1h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-2060,
1500
],
"parameters": {
"jsCode": "// Pull klines array from JSON\nconst klines = $input.first().json.klines;\n\n// === CONFIGURATION ===\nconst period = 14; // RSI period\n\n// === Extract closing prices ===\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// === Ensure enough data ===\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for RSI. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// === RSI Calculation ===\nfunction calculateRSI(prices, period) {\n const result = [];\n\n for (let i = period; i < prices.length; i++) {\n let gains = 0;\n let losses = 0;\n\n for (let j = i - period + 1; j <= i; j++) {\n const change = prices[j] - prices[j - 1];\n if (change >= 0) gains += change;\n else losses -= change;\n }\n\n const avgGain = gains / period;\n const avgLoss = losses / period;\n\n const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n const rsi = avgLoss === 0 ? 100 : 100 - (100 / (1 + rs));\n\n result.push({\n timestamp: klines[i][0],\n close: prices[i],\n rsi: rsi\n });\n }\n\n return result;\n}\n\n// === Run RSI ===\nconst rsiSeries = calculateRSI(closes, period);\n\n// === Return formatted RSI output ===\nreturn rsiSeries.map(r => ({\n json: {\n timestamp: r.timestamp,\n close: r.close,\n rsi: r.rsi\n }\n}));"
},
"typeVersion": 2
},
{
"id": "d16b7829-59ca-45ca-a5ae-4e315168c96d",
"name": "MACD (1h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-2060,
1720
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Parameters\nconst fastPeriod = 12;\nconst slowPeriod = 26;\nconst signalPeriod = 9;\n\n// Validate data length\nconst minRequired = slowPeriod + signalPeriod;\nif (closes.length < minRequired) {\n throw new Error(`Not enough data for MACD. Need at least ${minRequired}, got ${closes.length}`);\n}\n\n// === Helper: EMA function ===\nfunction calculateEMA(prices, period) {\n const k = 2 / (period + 1);\n const ema = [prices.slice(0, period).reduce((a, b) => a + b, 0) / period];\n\n for (let i = period; i < prices.length; i++) {\n ema.push(prices[i] * k + ema[ema.length - 1] * (1 - k));\n }\n\n return ema;\n}\n\n// === MACD Core Calculation ===\nconst slowEMA = calculateEMA(closes, slowPeriod);\nconst fastEMA = calculateEMA(closes.slice(slowPeriod - fastPeriod), fastPeriod);\n\n// Align lengths\nconst alignedFastEMA = fastEMA.slice(fastEMA.length - slowEMA.length);\nconst macdLine = alignedFastEMA.map((val, i) => val - slowEMA[i]);\n\n// Signal line\nconst signalLine = calculateEMA(macdLine, signalPeriod);\n\n// Histogram\nconst histogram = macdLine.slice(signalPeriod - 1).map((macd, i) => macd - signalLine[i]);\n\n// Final output start index\nconst startIndex = closes.length - histogram.length;\n\nconst result = [];\n\nfor (let i = 0; i < histogram.length; i++) {\n const idx = startIndex + i;\n result.push({\n timestamp: klines[idx]?.[0] || null,\n close: closes[idx],\n macd: macdLine[i + signalPeriod - 1],\n signal: signalLine[i],\n histogram: histogram[i]\n });\n}\n\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "15bf5c3b-de07-412b-988c-f5c59fa7a06f",
"name": "SMA (1h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-2060,
1960
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 50, 100, 200, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute SMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// Calculate SMA values\nconst result = [];\n\nfor (let i = period - 1; i < closes.length; i++) {\n const slice = closes.slice(i - period + 1, i + 1);\n const sum = slice.reduce((a, b) => a + b, 0);\n const average = sum / period;\n\n result.push({\n timestamp: klines[i][0],\n close: closes[i],\n sma: average\n });\n}\n\n// Return formatted output\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "83fa487a-1a67-4059-9007-d5298d8bb105",
"name": "EMA (1h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-2060,
2220
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 9, 12, 26, 50, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute EMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// EMA Calculation\nconst k = 2 / (period + 1);\nconst ema = [];\n\n// Start with SMA of first period\nlet sma = closes.slice(0, period).reduce((a, b) => a + b, 0) / period;\nema.push({\n timestamp: klines[period - 1][0],\n close: closes[period - 1],\n ema: sma\n});\n\n// Continue EMA calculation\nfor (let i = period; i < closes.length; i++) {\n const value = closes[i] * k + ema[ema.length - 1].ema * (1 - k);\n ema.push({\n timestamp: klines[i][0],\n close: closes[i],\n ema: value\n });\n}\n\n// Return result\nreturn ema.map(e => ({\n json: e\n}));"
},
"typeVersion": 2
},
{
"id": "7301ba32-ab0c-4c80-b041-cd398f7daa2c",
"name": "ADX1 berechnen",
"type": "n8n-nodes-base.code",
"position": [
-2060,
2420
],
"parameters": {
"jsCode": "// Get kline array from merged item\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 14;\n\n// Parse high, low, close arrays\nconst highs = klines.map(k => parseFloat(k[2]));\nconst lows = klines.map(k => parseFloat(k[3]));\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Validation\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for ADX. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// Initialize arrays\nconst tr = [];\nconst plusDM = [];\nconst minusDM = [];\n\n// Step 1: Calculate TR, +DM, -DM\nfor (let i = 1; i < klines.length; i++) {\n const highDiff = highs[i] - highs[i - 1];\n const lowDiff = lows[i - 1] - lows[i];\n const upMove = highDiff > 0 && highDiff > lowDiff ? highDiff : 0;\n const downMove = lowDiff > 0 && lowDiff > highDiff ? lowDiff : 0;\n\n const trueRange = Math.max(\n highs[i] - lows[i],\n Math.abs(highs[i] - closes[i - 1]),\n Math.abs(lows[i] - closes[i - 1])\n );\n\n tr.push(trueRange);\n plusDM.push(upMove);\n minusDM.push(downMove);\n}\n\n// Step 2: Smooth TR, +DM, -DM and calculate DI\nconst smoothedTR = [tr.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedPlusDM = [plusDM.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedMinusDM = [minusDM.slice(0, period).reduce((a, b) => a + b, 0)];\n\nfor (let i = period; i < tr.length; i++) {\n smoothedTR.push(smoothedTR[smoothedTR.length - 1] - smoothedTR[smoothedTR.length - 1] / period + tr[i]);\n smoothedPlusDM.push(smoothedPlusDM[smoothedPlusDM.length - 1] - smoothedPlusDM[smoothedPlusDM.length - 1] / period + plusDM[i]);\n smoothedMinusDM.push(smoothedMinusDM[smoothedMinusDM.length - 1] - smoothedMinusDM[smoothedMinusDM.length - 1] / period + minusDM[i]);\n}\n\nconst plusDI = smoothedPlusDM.map((val, i) => 100 * val / smoothedTR[i]);\nconst minusDI = smoothedMinusDM.map((val, i) => 100 * val / smoothedTR[i]);\n\n// Step 3: Calculate DX\nconst dx = plusDI.map((val, i) => {\n const diff = Math.abs(plusDI[i] - minusDI[i]);\n const sum = plusDI[i] + minusDI[i];\n return sum === 0 ? 0 : 100 * (diff / sum);\n});\n\n// Step 4: Smooth DX into ADX\nconst adx = [];\nconst firstADX = dx.slice(0, period).reduce((a, b) => a + b, 0) / period;\nadx.push(firstADX);\n\nfor (let i = period; i < dx.length; i++) {\n const newADX = (adx[adx.length - 1] * (period - 1) + dx[i]) / period;\n adx.push(newADX);\n}\n\n// Step 5: Final result formatting\nconst output = [];\n\nfor (let i = 0; i < adx.length; i++) {\n const index = i + (2 * period); // account for offset\n if (klines[index]) {\n output.push({\n timestamp: klines[index][0],\n close: closes[index],\n adx: adx[i],\n plusDI: plusDI[i + period],\n minusDI: minusDI[i + period]\n });\n }\n}\n\nreturn output.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "9ec777b1-eb23-43b0-8bb3-726adcc3418f",
"name": "HTTP Request 1h",
"type": "n8n-nodes-base.httpRequest",
"position": [
-2880,
1760
],
"parameters": {
"url": "https://api.binance.com/api/v3/klines",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "symbol",
"value": "={{$json.body.symbol}}"
},
{
"name": "interval",
"value": "1h"
},
{
"name": "limit",
"value": "40"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "c4a718f8-f2d6-464b-8120-1e4067d760ad",
"name": "Webhook 4h Indikatoren",
"type": "n8n-nodes-base.webhook",
"position": [
-40,
1680
],
"webhookId": "55fd9665-ed4a-4e1a-8062-890cad0fb6ac",
"parameters": {
"path": "55fd9665-ed4a-4e1a-8062-890cad0fb6ac",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "bbb81a2a-b1c4-4c1e-80e9-a4990c45fae8",
"name": "HTTP Request 4h",
"type": "n8n-nodes-base.httpRequest",
"position": [
300,
1680
],
"parameters": {
"url": "https://api.binance.com/api/v3/klines",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "symbol",
"value": "={{$json.body.symbol}}"
},
{
"name": "interval",
"value": "4h"
},
{
"name": "limit",
"value": "40"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "20e58706-035f-46ef-b235-78fe468875bc",
"name": "In 1 Array 4h zusammenführen",
"type": "n8n-nodes-base.code",
"position": [
640,
1680
],
"parameters": {
"jsCode": "const klines = $input.all().map(item => item.json);\nreturn [{ json: { klines } }];"
},
"typeVersion": 2
},
{
"id": "1675168b-97ab-4be4-92d2-734d075e2222",
"name": "Bollinger Bands (4h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
1120,
1180
],
"parameters": {
"jsCode": "// Get raw klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20;\nconst stdMultiplier = 2;\n\n// Validate type\nif (!Array.isArray(klines)) {\n throw new Error(\"klines is not an array\");\n}\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Ensure enough data\nif (closes.length < period) {\n throw new Error(`Not enough data: got ${closes.length}, expected at least ${period}`);\n}\n\n// BB calculation logic\nfunction calculateBB(prices, period) {\n const result = [];\n for (let i = period - 1; i < prices.length; i++) {\n const slice = prices.slice(i - period + 1, i + 1);\n const mean = slice.reduce((sum, val) => sum + val, 0) / period;\n const variance = slice.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / period;\n const stdDev = Math.sqrt(variance);\n\n result.push({\n close: prices[i],\n basis: mean,\n upper: mean + stdMultiplier * stdDev,\n lower: mean - stdMultiplier * stdDev,\n timestamp: klines[i][0]\n });\n }\n return result;\n}\n\n// Calculate bands\nconst bands = calculateBB(closes, period);\n\n// Format output\nreturn bands.map(b => ({\n json: {\n timestamp: b.timestamp,\n close: b.close,\n bb_basis: b.basis,\n bb_upper: b.upper,\n bb_lower: b.lower\n }\n}));"
},
"typeVersion": 2
},
{
"id": "d1c2fcc7-65ac-446c-8f59-c4cd8ac7d795",
"name": "RSI (4h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
1120,
1420
],
"parameters": {
"jsCode": "// Pull klines array from JSON\nconst klines = $input.first().json.klines;\n\n// === CONFIGURATION ===\nconst period = 14; // RSI period\n\n// === Extract closing prices ===\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// === Ensure enough data ===\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for RSI. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// === RSI Calculation ===\nfunction calculateRSI(prices, period) {\n const result = [];\n\n for (let i = period; i < prices.length; i++) {\n let gains = 0;\n let losses = 0;\n\n for (let j = i - period + 1; j <= i; j++) {\n const change = prices[j] - prices[j - 1];\n if (change >= 0) gains += change;\n else losses -= change;\n }\n\n const avgGain = gains / period;\n const avgLoss = losses / period;\n\n const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n const rsi = avgLoss === 0 ? 100 : 100 - (100 / (1 + rs));\n\n result.push({\n timestamp: klines[i][0],\n close: prices[i],\n rsi: rsi\n });\n }\n\n return result;\n}\n\n// === Run RSI ===\nconst rsiSeries = calculateRSI(closes, period);\n\n// === Return formatted RSI output ===\nreturn rsiSeries.map(r => ({\n json: {\n timestamp: r.timestamp,\n close: r.close,\n rsi: r.rsi\n }\n}));"
},
"typeVersion": 2
},
{
"id": "df32e55c-2dbc-44d6-8161-f70db651cfcd",
"name": "MACD (4h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
1120,
1660
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Parameters\nconst fastPeriod = 12;\nconst slowPeriod = 26;\nconst signalPeriod = 9;\n\n// Validate data length\nconst minRequired = slowPeriod + signalPeriod;\nif (closes.length < minRequired) {\n throw new Error(`Not enough data for MACD. Need at least ${minRequired}, got ${closes.length}`);\n}\n\n// === Helper: EMA function ===\nfunction calculateEMA(prices, period) {\n const k = 2 / (period + 1);\n const ema = [prices.slice(0, period).reduce((a, b) => a + b, 0) / period];\n\n for (let i = period; i < prices.length; i++) {\n ema.push(prices[i] * k + ema[ema.length - 1] * (1 - k));\n }\n\n return ema;\n}\n\n// === MACD Core Calculation ===\nconst slowEMA = calculateEMA(closes, slowPeriod);\nconst fastEMA = calculateEMA(closes.slice(slowPeriod - fastPeriod), fastPeriod);\n\n// Align lengths\nconst alignedFastEMA = fastEMA.slice(fastEMA.length - slowEMA.length);\nconst macdLine = alignedFastEMA.map((val, i) => val - slowEMA[i]);\n\n// Signal line\nconst signalLine = calculateEMA(macdLine, signalPeriod);\n\n// Histogram\nconst histogram = macdLine.slice(signalPeriod - 1).map((macd, i) => macd - signalLine[i]);\n\n// Final output start index\nconst startIndex = closes.length - histogram.length;\n\nconst result = [];\n\nfor (let i = 0; i < histogram.length; i++) {\n const idx = startIndex + i;\n result.push({\n timestamp: klines[idx]?.[0] || null,\n close: closes[idx],\n macd: macdLine[i + signalPeriod - 1],\n signal: signalLine[i],\n histogram: histogram[i]\n });\n}\n\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "93a115f7-e876-43f0-8ecb-70a47a06f41c",
"name": "SMA (4h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
1120,
1880
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 50, 100, 200, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute SMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// Calculate SMA values\nconst result = [];\n\nfor (let i = period - 1; i < closes.length; i++) {\n const slice = closes.slice(i - period + 1, i + 1);\n const sum = slice.reduce((a, b) => a + b, 0);\n const average = sum / period;\n\n result.push({\n timestamp: klines[i][0],\n close: closes[i],\n sma: average\n });\n}\n\n// Return formatted output\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "17bf4e9f-7053-4a04-b439-3e23fe5cb7f9",
"name": "EMA (4h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
1120,
2100
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 9, 12, 26, 50, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute EMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// EMA Calculation\nconst k = 2 / (period + 1);\nconst ema = [];\n\n// Start with SMA of first period\nlet sma = closes.slice(0, period).reduce((a, b) => a + b, 0) / period;\nema.push({\n timestamp: klines[period - 1][0],\n close: closes[period - 1],\n ema: sma\n});\n\n// Continue EMA calculation\nfor (let i = period; i < closes.length; i++) {\n const value = closes[i] * k + ema[ema.length - 1].ema * (1 - k);\n ema.push({\n timestamp: klines[i][0],\n close: closes[i],\n ema: value\n });\n}\n\n// Return result\nreturn ema.map(e => ({\n json: e\n}));"
},
"typeVersion": 2
},
{
"id": "d61db420-9def-4ec1-bf8a-94afeabda186",
"name": "ADX (4h) berechnen",
"type": "n8n-nodes-base.code",
"position": [
1120,
2360
],
"parameters": {
"jsCode": "// Get kline array from merged item\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 14;\n\n// Parse high, low, close arrays\nconst highs = klines.map(k => parseFloat(k[2]));\nconst lows = klines.map(k => parseFloat(k[3]));\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Validation\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for ADX. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// Initialize arrays\nconst tr = [];\nconst plusDM = [];\nconst minusDM = [];\n\n// Step 1: Calculate TR, +DM, -DM\nfor (let i = 1; i < klines.length; i++) {\n const highDiff = highs[i] - highs[i - 1];\n const lowDiff = lows[i - 1] - lows[i];\n const upMove = highDiff > 0 && highDiff > lowDiff ? highDiff : 0;\n const downMove = lowDiff > 0 && lowDiff > highDiff ? lowDiff : 0;\n\n const trueRange = Math.max(\n highs[i] - lows[i],\n Math.abs(highs[i] - closes[i - 1]),\n Math.abs(lows[i] - closes[i - 1])\n );\n\n tr.push(trueRange);\n plusDM.push(upMove);\n minusDM.push(downMove);\n}\n\n// Step 2: Smooth TR, +DM, -DM and calculate DI\nconst smoothedTR = [tr.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedPlusDM = [plusDM.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedMinusDM = [minusDM.slice(0, period).reduce((a, b) => a + b, 0)];\n\nfor (let i = period; i < tr.length; i++) {\n smoothedTR.push(smoothedTR[smoothedTR.length - 1] - smoothedTR[smoothedTR.length - 1] / period + tr[i]);\n smoothedPlusDM.push(smoothedPlusDM[smoothedPlusDM.length - 1] - smoothedPlusDM[smoothedPlusDM.length - 1] / period + plusDM[i]);\n smoothedMinusDM.push(smoothedMinusDM[smoothedMinusDM.length - 1] - smoothedMinusDM[smoothedMinusDM.length - 1] / period + minusDM[i]);\n}\n\nconst plusDI = smoothedPlusDM.map((val, i) => 100 * val / smoothedTR[i]);\nconst minusDI = smoothedMinusDM.map((val, i) => 100 * val / smoothedTR[i]);\n\n// Step 3: Calculate DX\nconst dx = plusDI.map((val, i) => {\n const diff = Math.abs(plusDI[i] - minusDI[i]);\n const sum = plusDI[i] + minusDI[i];\n return sum === 0 ? 0 : 100 * (diff / sum);\n});\n\n// Step 4: Smooth DX into ADX\nconst adx = [];\nconst firstADX = dx.slice(0, period).reduce((a, b) => a + b, 0) / period;\nadx.push(firstADX);\n\nfor (let i = period; i < dx.length; i++) {\n const newADX = (adx[adx.length - 1] * (period - 1) + dx[i]) / period;\n adx.push(newADX);\n}\n\n// Step 5: Final result formatting\nconst output = [];\n\nfor (let i = 0; i < adx.length; i++) {\n const index = i + (2 * period); // account for offset\n if (klines[index]) {\n output.push({\n timestamp: klines[index][0],\n close: closes[index],\n adx: adx[i],\n plusDI: plusDI[i + period],\n minusDI: minusDI[i + period]\n });\n }\n}\n\nreturn output.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"name": "4h Indikatoren zusammenführen",
"type": "n8n-nodes-base.merge",
"position": [
1720,
1600
],
"parameters": {
"numberInputs": 6
},
"typeVersion": 3.1
},
{
"id": "8585a269-b70d-4af7-b264-db9f638c8a77",
"name": "Auf 4h Webhook antworten",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
2120,
1660
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.3
},
{
"id": "91a05310-bd36-4ee0-8381-b3d16c3346be",
"name": "Webhook 1d Indikatoren",
"type": "n8n-nodes-base.webhook",
"position": [
-1600,
3140
],
"webhookId": "23c8ec04-5aec-49c6-9c2c-c352ccec11b4",
"parameters": {
"path": "23c8ec04-5aec-49c6-9c2c-c352ccec11b4",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "29121e2e-f6e2-4d42-8e5b-e8eea1e61ec8",
"name": "HTTP Request 1d",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1260,
3140
],
"parameters": {
"url": "https://api.binance.com/api/v3/klines",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "symbol",
"value": "={{$json.body.symbol}}"
},
{
"name": "interval",
"value": "1d"
},
{
"name": "limit",
"value": "40"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "1be26316-3d08-4983-9d12-6bc36465e76e",
"name": "In 1 Array 1d zusammenführen",
"type": "n8n-nodes-base.code",
"position": [
-900,
3140
],
"parameters": {
"jsCode": "const klines = $input.all().map(item => item.json);\nreturn [{ json: { klines } }];"
},
"typeVersion": 2
},
{
"id": "6e9c7976-737b-4377-b412-633a1a67097b",
"name": "Bollinger Bands (1d) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-440,
2620
],
"parameters": {
"jsCode": "// Get raw klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20;\nconst stdMultiplier = 2;\n\n// Validate type\nif (!Array.isArray(klines)) {\n throw new Error(\"klines is not an array\");\n}\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Ensure enough data\nif (closes.length < period) {\n throw new Error(`Not enough data: got ${closes.length}, expected at least ${period}`);\n}\n\n// BB calculation logic\nfunction calculateBB(prices, period) {\n const result = [];\n for (let i = period - 1; i < prices.length; i++) {\n const slice = prices.slice(i - period + 1, i + 1);\n const mean = slice.reduce((sum, val) => sum + val, 0) / period;\n const variance = slice.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / period;\n const stdDev = Math.sqrt(variance);\n\n result.push({\n close: prices[i],\n basis: mean,\n upper: mean + stdMultiplier * stdDev,\n lower: mean - stdMultiplier * stdDev,\n timestamp: klines[i][0]\n });\n }\n return result;\n}\n\n// Calculate bands\nconst bands = calculateBB(closes, period);\n\n// Format output\nreturn bands.map(b => ({\n json: {\n timestamp: b.timestamp,\n close: b.close,\n bb_basis: b.basis,\n bb_upper: b.upper,\n bb_lower: b.lower\n }\n}));"
},
"typeVersion": 2
},
{
"id": "ac84877a-75cf-4ef2-bad1-8d0f444ecead",
"name": "RSI (1d) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-440,
2880
],
"parameters": {
"jsCode": "// Pull klines array from JSON\nconst klines = $input.first().json.klines;\n\n// === CONFIGURATION ===\nconst period = 14; // RSI period\n\n// === Extract closing prices ===\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// === Ensure enough data ===\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for RSI. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// === RSI Calculation ===\nfunction calculateRSI(prices, period) {\n const result = [];\n\n for (let i = period; i < prices.length; i++) {\n let gains = 0;\n let losses = 0;\n\n for (let j = i - period + 1; j <= i; j++) {\n const change = prices[j] - prices[j - 1];\n if (change >= 0) gains += change;\n else losses -= change;\n }\n\n const avgGain = gains / period;\n const avgLoss = losses / period;\n\n const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n const rsi = avgLoss === 0 ? 100 : 100 - (100 / (1 + rs));\n\n result.push({\n timestamp: klines[i][0],\n close: prices[i],\n rsi: rsi\n });\n }\n\n return result;\n}\n\n// === Run RSI ===\nconst rsiSeries = calculateRSI(closes, period);\n\n// === Return formatted RSI output ===\nreturn rsiSeries.map(r => ({\n json: {\n timestamp: r.timestamp,\n close: r.close,\n rsi: r.rsi\n }\n}));"
},
"typeVersion": 2
},
{
"id": "a5da65c5-db5a-4f9d-a6cf-228f081ffb3c",
"name": "MACD (1d) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-440,
3120
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Parameters\nconst fastPeriod = 12;\nconst slowPeriod = 26;\nconst signalPeriod = 9;\n\n// Validate data length\nconst minRequired = slowPeriod + signalPeriod;\nif (closes.length < minRequired) {\n throw new Error(`Not enough data for MACD. Need at least ${minRequired}, got ${closes.length}`);\n}\n\n// === Helper: EMA function ===\nfunction calculateEMA(prices, period) {\n const k = 2 / (period + 1);\n const ema = [prices.slice(0, period).reduce((a, b) => a + b, 0) / period];\n\n for (let i = period; i < prices.length; i++) {\n ema.push(prices[i] * k + ema[ema.length - 1] * (1 - k));\n }\n\n return ema;\n}\n\n// === MACD Core Calculation ===\nconst slowEMA = calculateEMA(closes, slowPeriod);\nconst fastEMA = calculateEMA(closes.slice(slowPeriod - fastPeriod), fastPeriod);\n\n// Align lengths\nconst alignedFastEMA = fastEMA.slice(fastEMA.length - slowEMA.length);\nconst macdLine = alignedFastEMA.map((val, i) => val - slowEMA[i]);\n\n// Signal line\nconst signalLine = calculateEMA(macdLine, signalPeriod);\n\n// Histogram\nconst histogram = macdLine.slice(signalPeriod - 1).map((macd, i) => macd - signalLine[i]);\n\n// Final output start index\nconst startIndex = closes.length - histogram.length;\n\nconst result = [];\n\nfor (let i = 0; i < histogram.length; i++) {\n const idx = startIndex + i;\n result.push({\n timestamp: klines[idx]?.[0] || null,\n close: closes[idx],\n macd: macdLine[i + signalPeriod - 1],\n signal: signalLine[i],\n histogram: histogram[i]\n });\n}\n\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "5b1f34b3-e675-46b1-a754-679080680058",
"name": "SMA (1d) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-440,
3340
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 50, 100, 200, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute SMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// Calculate SMA values\nconst result = [];\n\nfor (let i = period - 1; i < closes.length; i++) {\n const slice = closes.slice(i - period + 1, i + 1);\n const sum = slice.reduce((a, b) => a + b, 0);\n const average = sum / period;\n\n result.push({\n timestamp: klines[i][0],\n close: closes[i],\n sma: average\n });\n}\n\n// Return formatted output\nreturn result.map(r => ({\n json: r\n}));"
},
"typeVersion": 2
},
{
"id": "0b3278a6-5793-4d70-8954-70562c43a3eb",
"name": "EMA (1d) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-440,
3580
],
"parameters": {
"jsCode": "// Get klines array\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 20; // Change to 9, 12, 26, 50, etc. as needed\n\n// Extract closing prices\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Check for sufficient data\nif (closes.length < period) {\n throw new Error(`Not enough data to compute EMA. Need at least ${period}, got ${closes.length}`);\n}\n\n// EMA Calculation\nconst k = 2 / (period + 1);\nconst ema = [];\n\n// Start with SMA of first period\nlet sma = closes.slice(0, period).reduce((a, b) => a + b, 0) / period;\nema.push({\n timestamp: klines[period - 1][0],\n close: closes[period - 1],\n ema: sma\n});\n\n// Continue EMA calculation\nfor (let i = period; i < closes.length; i++) {\n const value = closes[i] * k + ema[ema.length - 1].ema * (1 - k);\n ema.push({\n timestamp: klines[i][0],\n close: closes[i],\n ema: value\n });\n}\n\n// Return result\nreturn ema.map(e => ({\n json: e\n}));"
},
"typeVersion": 2
},
{
"id": "28dd6fb1-a161-49ed-9c14-740e88e2195d",
"name": "ADX (1d) berechnen",
"type": "n8n-nodes-base.code",
"position": [
-440,
3780
],
"parameters": {
"jsCode": "// Get kline array from merged item\nconst klines = $input.first().json.klines;\n\n// Parameters\nconst period = 14;\n\n// Parse high, low, close arrays\nconst highs = klines.map(k => parseFloat(k[2]));\nconst lows = klines.map(k => parseFloat(k[3]));\nconst closes = klines.map(k => parseFloat(k[4]));\n\n// Validation\nif (closes.length < period + 1) {\n throw new Error(`Not enough data for ADX. Need at least ${period + 1}, got ${closes.length}`);\n}\n\n// Initialize arrays\nconst tr = [];\nconst plusDM = [];\nconst minusDM = [];\n\n// Step 1: Calculate TR, +DM, -DM\nfor (let i = 1; i < klines.length; i++) {\n const highDiff = highs[i] - highs[i - 1];\n const lowDiff = lows[i - 1] - lows[i];\n const upMove = highDiff > 0 && highDiff > lowDiff ? highDiff : 0;\n const downMove = lowDiff > 0 && lowDiff > highDiff ? lowDiff : 0;\n\n const trueRange = Math.max(\n highs[i] - lows[i],\n Math.abs(highs[i] - closes[i - 1]),\n Math.abs(lows[i] - closes[i - 1])\n );\n\n tr.push(trueRange);\n plusDM.push(upMove);\n minusDM.push(downMove);\n}\n\n// Step 2: Smooth TR, +DM, -DM and calculate DI\nconst smoothedTR = [tr.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedPlusDM = [plusDM.slice(0, period).reduce((a, b) => a + b, 0)];\nconst smoothedMinusDM = [minusDM.slice(0, period).reduce((a, b) => a + b, 0)];\n\nfor (let i = period; i < tr.length; i++) {\n smoothedTR.push(smoothedTR[smoothedTR.length - 1] - smoothedTR[smoothedTR.length - 1] / period + tr[i]);\n smoothedPlusDM.push(smoothedPlusDM[smoothedPlusDM.length - 1] - smoothedPlusDM[smoothedPlusDM.length - 1] / period + plusDM[i]);\n smoothedMinusDM.push(smoothedMinusDM[smoothedMinusDM.length - 1] - smoothedMinusDM[smoothedMinusDM.length - 1] / period + minusDM[i]);\n}\n\nconst plusDI = smoothedPlusDM.map((val, i) => 100 * val / smoothedTR[i]);\nconst minusDI = smoothedMinusDM.map((val, i) => 100 * val / smoothedTR[i]);\n\n// Step 3: Calculate DX\nconst dx = plusDI.map((val, i) => {\n const diff = Math.abs(plusDI[i] - minusDI[i]);\n const sum = plusDI[i] + minusDI[i];\n return sum === 0 ? 0 : 100 * (diff / sum);\n});\n\n// Step 4: Smooth DX into ADX\nconst adx = [];\nconst firstADX = dx.slice(0, period).reduce((a, b) => a + b, 0) / period;\nadx.push(firstADX);\n\nfor (let i = period; i < dx.length; i++) {\n const newADX = (adx[adx.length - 1] * (period - 1) + dx[i]) / period;\n adx.push(newADX);\n}\n\n// Step 5: Final result formatting\nconst output = [];\n\nfor (let i = 0; i < adx.length; i++) {\n const index = i + (2 * period); // account for offset\n if (klines[index]) {\n output.push({\n timestamp: klines[index][0],\n close: closes[index],\n adx: adx[i],\n plusDI: plusDI[i + period],\n minusDI: minusDI[i + period]\n });\n }\n}\n\nreturn output.map(r => ({ json: r }));"
},
"typeVersion": 2
},
{
"id": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"name": "1d Indikatoren zusammenführen",
"type": "n8n-nodes-base.merge",
"position": [
160,
3060
],
"parameters": {
"numberInputs": 6
},
"typeVersion": 3.1
},
{
"id": "939665ce-7a50-4a6d-9b37-62ad800350b0",
"name": "Auf 1d Webhook antworten",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
560,
3120
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.3
},
{
"id": "2f44a150-0c5a-4b74-92b5-fe941fccb86d",
"name": "Notizzettel13",
"type": "n8n-nodes-base.stickyNote",
"position": [
100,
-340
],
"parameters": {
"color": 5,
"width": 260,
"height": 620,
"content": "## Technical Indicator API Merge \n\n**Binance API** for 6 indicators:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "fbf6424d-8bfc-469b-ae56-c9824e657e75",
"name": "Notizzettel",
"type": "n8n-nodes-base.stickyNote",
"position": [
1640,
1340
],
"parameters": {
"color": 5,
"width": 260,
"height": 620,
"content": "## Technical Indicator API Merge \n\n**Binance API** for 6 indicators:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "fba15cd9-e7a0-4a03-813e-444dd2cd25f7",
"name": "Notizzettel14",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1540,
1380
],
"parameters": {
"color": 5,
"width": 260,
"height": 620,
"content": "## Technical Indicator API Merge \n\n**Binance API** for 6 indicators:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "ab87eb1b-3048-4717-af97-b7fa92c0f260",
"name": "Notizzettel15",
"type": "n8n-nodes-base.stickyNote",
"position": [
80,
2760
],
"parameters": {
"color": 5,
"width": 260,
"height": 620,
"content": "## Technical Indicator API Merge \n\n**Binance API** for 6 indicators:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "b3abceb1-3605-4cca-8b4e-1f85f792fff2",
"name": "Notizzettel1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1540,
-500
],
"parameters": {
"color": 4,
"height": 680,
"content": "## Webhooks (15minData)\n\n• **Entry point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "2143ce8a-8746-4187-bc43-c9cc294da7b8",
"name": "Notizzettel2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3300,
1240
],
"parameters": {
"color": 4,
"height": 680,
"content": "## Webhooks (1hourData)\n\n• **Entry point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "d9150fb0-42b5-48e8-b123-e588672a653f",
"name": "Notizzettel3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-100,
1200
],
"parameters": {
"color": 4,
"height": 680,
"content": "## Webhooks (4hourData)\n\n• **Entry point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "50737e51-ef67-42af-bf15-ac228c750f4d",
"name": "Notizzettel4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1680,
2640
],
"parameters": {
"color": 4,
"height": 680,
"content": "## Webhooks (1dayData)\n\n• **Entry point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "61972dcf-2bd5-454e-880b-0d3e97c82f98",
"name": "Notizzettel5",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
-480
],
"parameters": {
"color": 4,
"width": 280,
"height": 640,
"content": "## Webhooks Respond (15minData)\n\n• **Exit point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "c545e86b-8f90-4e3b-8e72-25f56de0b214",
"name": "Notizzettel6",
"type": "n8n-nodes-base.stickyNote",
"position": [
2020,
1200
],
"parameters": {
"color": 4,
"width": 280,
"height": 640,
"content": "## Webhooks Respond (4hourData)\n\n• **Exit point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "9e838383-1c81-45c6-98f1-f735dc5789df",
"name": "Notizzettel7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1140,
1260
],
"parameters": {
"color": 4,
"width": 280,
"height": 640,
"content": "## Webhooks Respond (1hourData)\n\n• **Exit point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "f05d2def-9593-46c5-862d-378a5d1f64d4",
"name": "Notizzettel8",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
2660
],
"parameters": {
"color": 4,
"width": 280,
"height": 640,
"content": "## Webhooks Respond (1dayData)\n\n• **Exit point** for external workflows calling indicator batches\n\n• Orchestrates trigger for **indicator API pull + formatter nodes**\n\n• Returns **cleaned batch** back via Respond to Webhook node\n\n📎 Notes:\n\n• Must pass through correct **webhook** path\n\n• Responds after **merge with all 6 formatted outputs** per timeframe"
},
"typeVersion": 1
},
{
"id": "ceb5f8e0-e51f-4554-a752-a319033c14c4",
"name": "Notizzettel9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1160,
-300
],
"parameters": {
"color": 6,
"width": 260,
"height": 520,
"content": "## Binance API Calls 15m \n\n• Triggers **Binance API** for k-line data:\n\n\n• Each node pulls and returns **raw API data** for formatting"
},
"typeVersion": 1
},
{
"id": "8e1aeb88-3232-4ea7-85c3-49a75097341b",
"name": "Notizzettel10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2940,
1480
],
"parameters": {
"color": 6,
"width": 260,
"height": 500,
"content": "## Binance API Calls 1h \n\n• Triggers **Binance API** for k-line data:\n\n\n• Each node pulls and returns **raw API data** for formatting"
},
"typeVersion": 1
},
{
"id": "53996473-bdd7-44d3-9060-96a2f072077c",
"name": "Notizzettel11",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
1420
],
"parameters": {
"color": 6,
"width": 260,
"height": 500,
"content": "## Binance API Calls 4h \n\n• Triggers **Binance API** for k-line data:\n\n\n• Each node pulls and returns **raw API data** for formatting"
},
"typeVersion": 1
},
{
"id": "6b138f55-5f0e-4844-a570-47919c8888b5",
"name": "Notizzettel12",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1340,
2920
],
"parameters": {
"color": 6,
"width": 260,
"height": 420,
"content": "## Binance API Calls 1d \n\n• Triggers **Binance API** for k-line data:\n\n\n• Each node pulls and returns **raw API data** for formatting"
},
"typeVersion": 1
},
{
"id": "8d8bd17f-c437-4e57-a517-3b6eb44eeff7",
"name": "Notizzettel16",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2120,
720
],
"parameters": {
"color": 2,
"height": 1860,
"content": "## Calculate Technical Indicators \n \n\n• Ensures consistent **downstream format for merge and reasoning**\n\n📎 Notes:\n\n• **Format logic** is customized per indicator\n\n• Essential for **standardizing multi-timeframe data ingestion**"
},
"typeVersion": 1
},
{
"id": "ee6e6788-7b9d-4d29-9cdd-0af5256289ef",
"name": "Notizzettel17",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-860
],
"parameters": {
"color": 2,
"width": 260,
"height": 1720,
"content": "## Calculate Technical Indicators \n \n\n• Ensures consistent **downstream format for merge and reasoning**\n\n📎 Notes:\n\n• **Format logic** is customized per indicator\n\n• Essential for **standardizing multi-timeframe data ingestion**"
},
"typeVersion": 1
},
{
"id": "e53bcd92-c603-43f3-b25f-0d7dd46afca0",
"name": "Notizzettel18",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
720
],
"parameters": {
"color": 2,
"width": 260,
"height": 1820,
"content": "## Calculate Technical Indicators \n \n\n• Ensures consistent **downstream format for merge and reasoning**\n\n📎 Notes:\n\n• **Format logic** is customized per indicator\n\n• Essential for **standardizing multi-timeframe data ingestion**"
},
"typeVersion": 1
},
{
"id": "7d27698c-bbc5-4faf-aa41-4c4332abb484",
"name": "Notizzettel19",
"type": "n8n-nodes-base.stickyNote",
"position": [
-520,
2180
],
"parameters": {
"color": 2,
"width": 260,
"height": 1800,
"content": "## Calculate Technical Indicators \n \n\n• Ensures consistent **downstream format for merge and reasoning**\n\n📎 Notes:\n\n• **Format logic** is customized per indicator\n\n• Essential for **standardizing multi-timeframe data ingestion**"
},
"typeVersion": 1
},
{
"id": "309f22d1-aeb2-4d48-a7c4-deaad51070e3",
"name": "Notizzettel20",
"type": "n8n-nodes-base.stickyNote",
"position": [
-820,
-240
],
"parameters": {
"color": 5,
"width": 260,
"height": 460,
"content": "## API Merge \n\n**Binance API** for k-line Data to calculate:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "5a27535c-5bc9-4718-b895-5a8eccf37974",
"name": "Notizzettel21",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2600,
1560
],
"parameters": {
"color": 5,
"width": 260,
"height": 420,
"content": "## API Merge \n\n**Binance API** for k-line Data to calculate:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "52180c40-a1d3-4c41-aea6-73f62f7c98ee",
"name": "Notizzettel22",
"type": "n8n-nodes-base.stickyNote",
"position": [
-980,
2920
],
"parameters": {
"color": 5,
"width": 260,
"height": 460,
"content": "## API Merge \n\n**Binance API** for k-line Data to calculate:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "08697498-181c-417f-8027-8d6de1471bed",
"name": "Notizzettel23",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
1480
],
"parameters": {
"color": 5,
"width": 260,
"height": 440,
"content": "## API Merge \n\n**Binance API** for k-line Data to calculate:\n\n• **RSI, MACD, BBANDS, SMA, EMA, ADX**"
},
"typeVersion": 1
},
{
"id": "773a2b4f-f716-41ab-ba18-1412e2dd50e5",
"name": "Notizzettel24",
"type": "n8n-nodes-base.stickyNote",
"position": [
2800,
-60
],
"parameters": {
"width": 1460,
"height": 3020,
"content": "# 🧪 Binance SM Indicators Webhook Tool – Documentation\n\nA backend webhook processor that performs **real-time indicator calculations** for 15m, 1h, 4h, and 1d Binance candlestick data. This workflow powers all the indicator sub-agents and is essential for maintaining modular and scalable logic across timeframes.\n\n---\n\n## 🎯 Purpose\n\n* Accepts HTTP POST requests from the 15m, 1h, 4h, or 1d sub-agents\n* Pulls raw OHLCV kline data for the symbol and interval\n* Calculates technical indicators:\n\n * RSI, MACD, Bollinger Bands, SMA, EMA, ADX\n* Returns structured JSON with labeled values (e.g., `\"MACD_Cross\": \"Bullish\"`)\n\nThis tool ensures **centralized logic reuse** across all timeframe agents while improving speed and maintainability.\n\n---\n\n## ⚙️ Key Components\n\n| Node Name | Description |\n| ---------------------- | --------------------------------------------------------- |\n| `Webhook Trigger` | Handles POST at `/15m-indicators`, `/1h-indicators`, etc. |\n| `Extract Symbol` | Validates input payload (must include `symbol`) |\n| `Fetch Binance Klines` | Gets latest 100 candles using `/api/v3/klines` |\n| `RSI Calculator` | Computes 14-period RSI from closing prices |\n| `MACD Calculator` | Computes 12, 26, 9 MACD with signal and histogram |\n| `BBANDS Calculator` | Calculates 20-period bands using std. deviation |\n| `SMA/EMA Node` | Computes 20-period simple and exponential MAs |\n| `ADX Calculator` | Computes 14-period trend strength (DI+/DI− included) |\n| `Prepare Output` | Returns JSON with all labeled indicators |\n\n---\n\n## 📥 Expected Input (from sub-agent)\n\n```json\n{\n \"symbol\": \"BTCUSDT\"\n}\n```\n\nMust be a valid Binance Spot trading pair. Interval is auto-routed based on webhook endpoint:\n\n| Endpoint Path | Interval |\n| ----------------- | -------- |\n| `/15m-indicators` | 15m |\n| `/1h-indicators` | 1h |\n| `/4h-indicators` | 4h |\n| `/1d-indicators` | 1d |\n\n---\n\n## 📊 Sample Output JSON\n\n```json\n{\n \"symbol\": \"BTCUSDT\",\n \"interval\": \"4h\",\n \"rsi\": 65.1,\n \"macd\": {\n \"value\": 24.3,\n \"signal\": 21.7,\n \"histogram\": 2.6,\n \"cross\": \"Bullish\"\n },\n \"bb\": {\n \"basis\": 62600,\n \"upper\": 63500,\n \"lower\": 61700,\n \"status\": \"Expanding\"\n },\n \"sma\": 62000,\n \"ema\": 62400,\n \"adx\": {\n \"value\": 32.8,\n \"strength\": \"Strong\"\n }\n}\n```\n\n---\n\n## 🧩 Use Case Scenarios\n\n| Scenario | Result |\n| ------------------------------------------ | -------------------------------------------------------- |\n| 15m tool POSTs to `/15m-indicators` | Webhook responds with 15m indicator set |\n| Financial Analyst Tool requests 1h signals | This workflow handles the actual math for each indicator |\n| 1d tool needs RSI + MACD + ADX | Centralized logic avoids duplication across agents |\n\n---\n\n## 🛠️ Installation Instructions\n\n### 1. Import & Activate\n\n* Import JSON into n8n\n* Ensure webhook is live and accessible\n* Test each endpoint (e.g., `/1h-indicators`) via POST\n\n### 2. Connect to Binance API\n\n* Public API: no credentials required\n* Ensure the HTTP request node for klines uses:\n\n ```\n https://api.binance.com/api/v3/klines\n ```\n\n### 3. Link to Sub-Agent Workflows\n\n* 15m, 1h, 4h, 1d tools all depend on this for logic\n* Must POST `symbol` to the correct interval endpoint\n\n---\n\n## 📦 Example Workflow Integration\n\nAll the following tools rely on this:\n\n* `Binance SM 15min Indicators Tool`\n* `Binance SM 1hour Indicators Tool`\n* `Binance SM 4hour Indicators Tool`\n* `Binance SM 1day Indicators Tool`\n\nThis acts as the math engine behind each.\n\n---\n\n## 🔐 Licensing & Support\n\n🔗 **Don Jayamaha – LinkedIn**\n[http://linkedin.com/in/donjayamahajr](http://linkedin.com/in/donjayamahajr)\n\n© 2025 Treasurium Capital Limited Company. All rights reserved.\nThe design, architecture, and indicator calculation code within this system are proprietary. Reuse, resale, or modification without license is strictly prohibited.\n"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "f7032997-bb7f-4e2a-9982-7ee18c95cfbe",
"connections": {
"61cb3bd7-60ba-4dcf-a080-146b7612a99b": {
"main": [
[
{
"node": "46b937d5-7338-457f-b2f0-eb85ac44a8bb",
"type": "main",
"index": 0
}
]
]
},
"df6546be-3778-4fba-801a-870c0fe883c3": {
"main": [
[
{
"node": "5ea4756f-a20a-444c-8471-57d209457823",
"type": "main",
"index": 5
}
]
]
},
"25ef2964-c9b1-4b9e-b6ce-3766b215d163": {
"main": [
[
{
"node": "5ea4756f-a20a-444c-8471-57d209457823",
"type": "main",
"index": 4
}
]
]
},
"b0391e28-03a3-40f0-8182-72df0928ca2c": {
"main": [
[
{
"node": "5ea4756f-a20a-444c-8471-57d209457823",
"type": "main",
"index": 1
}
]
]
},
"c50f7fa5-2707-47a4-9b32-1d582bf5d600": {
"main": [
[
{
"node": "5ea4756f-a20a-444c-8471-57d209457823",
"type": "main",
"index": 3
}
]
]
},
"7301ba32-ab0c-4c80-b041-cd398f7daa2c": {
"main": [
[
{
"node": "af471a36-1107-4ccd-be14-efa06ba27330",
"type": "main",
"index": 5
}
]
]
},
"2c598960-630c-4687-91c0-bfae10da1943": {
"main": [
[
{
"node": "5ea4756f-a20a-444c-8471-57d209457823",
"type": "main",
"index": 2
}
]
]
},
"29121e2e-f6e2-4d42-8e5b-e8eea1e61ec8": {
"main": [
[
{
"node": "1be26316-3d08-4983-9d12-6bc36465e76e",
"type": "main",
"index": 0
}
]
]
},
"9ec777b1-eb23-43b0-8bb3-726adcc3418f": {
"main": [
[
{
"node": "d7d9bb31-6986-42e6-9f0c-7d7f00d66ee1",
"type": "main",
"index": 0
}
]
]
},
"bbb81a2a-b1c4-4c1e-80e9-a4990c45fae8": {
"main": [
[
{
"node": "20e58706-035f-46ef-b235-78fe468875bc",
"type": "main",
"index": 0
}
]
]
},
"0b3278a6-5793-4d70-8954-70562c43a3eb": {
"main": [
[
{
"node": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"type": "main",
"index": 4
}
]
]
},
"83fa487a-1a67-4059-9007-d5298d8bb105": {
"main": [
[
{
"node": "af471a36-1107-4ccd-be14-efa06ba27330",
"type": "main",
"index": 4
}
]
]
},
"17bf4e9f-7053-4a04-b439-3e23fe5cb7f9": {
"main": [
[
{
"node": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"type": "main",
"index": 4
}
]
]
},
"ac84877a-75cf-4ef2-bad1-8d0f444ecead": {
"main": [
[
{
"node": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"type": "main",
"index": 1
}
]
]
},
"702e8bc8-d8f0-4fb4-b44f-fd19479c8b03": {
"main": [
[
{
"node": "af471a36-1107-4ccd-be14-efa06ba27330",
"type": "main",
"index": 1
}
]
]
},
"d1c2fcc7-65ac-446c-8f59-c4cd8ac7d795": {
"main": [
[
{
"node": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"type": "main",
"index": 1
}
]
]
},
"5b1f34b3-e675-46b1-a754-679080680058": {
"main": [
[
{
"node": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"type": "main",
"index": 3
}
]
]
},
"15bf5c3b-de07-412b-988c-f5c59fa7a06f": {
"main": [
[
{
"node": "af471a36-1107-4ccd-be14-efa06ba27330",
"type": "main",
"index": 3
}
]
]
},
"93a115f7-e876-43f0-8ecb-70a47a06f41c": {
"main": [
[
{
"node": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"type": "main",
"index": 3
}
]
]
},
"28dd6fb1-a161-49ed-9c14-740e88e2195d": {
"main": [
[
{
"node": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"type": "main",
"index": 5
}
]
]
},
"d61db420-9def-4ec1-bf8a-94afeabda186": {
"main": [
[
{
"node": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"type": "main",
"index": 5
}
]
]
},
"a5da65c5-db5a-4f9d-a6cf-228f081ffb3c": {
"main": [
[
{
"node": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"type": "main",
"index": 2
}
]
]
},
"d16b7829-59ca-45ca-a5ae-4e315168c96d": {
"main": [
[
{
"node": "af471a36-1107-4ccd-be14-efa06ba27330",
"type": "main",
"index": 2
}
]
]
},
"df32e55c-2dbc-44d6-8161-f70db651cfcd": {
"main": [
[
{
"node": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"type": "main",
"index": 2
}
]
]
},
"46b937d5-7338-457f-b2f0-eb85ac44a8bb": {
"main": [
[
{
"node": "5b8c1049-bcf4-41d4-bba3-5f76e940bd3e",
"type": "main",
"index": 0
},
{
"node": "b0391e28-03a3-40f0-8182-72df0928ca2c",
"type": "main",
"index": 0
},
{
"node": "2c598960-630c-4687-91c0-bfae10da1943",
"type": "main",
"index": 0
},
{
"node": "c50f7fa5-2707-47a4-9b32-1d582bf5d600",
"type": "main",
"index": 0
},
{
"node": "25ef2964-c9b1-4b9e-b6ce-3766b215d163",
"type": "main",
"index": 0
},
{
"node": "df6546be-3778-4fba-801a-870c0fe883c3",
"type": "main",
"index": 0
}
]
]
},
"660dfcb4-ed63-4c53-806b-cba96c105fee": {
"main": [
[
{
"node": "939665ce-7a50-4a6d-9b37-62ad800350b0",
"type": "main",
"index": 0
}
]
]
},
"af471a36-1107-4ccd-be14-efa06ba27330": {
"main": [
[
{
"node": "39e6b058-d800-4751-b75b-5e62be379c61",
"type": "main",
"index": 0
}
]
]
},
"7940bc3f-c5f4-4b4b-b542-8737f17afbbf": {
"main": [
[
{
"node": "8585a269-b70d-4af7-b264-db9f638c8a77",
"type": "main",
"index": 0
}
]
]
},
"1be26316-3d08-4983-9d12-6bc36465e76e": {
"main": [
[
{
"node": "6e9c7976-737b-4377-b412-633a1a67097b",
"type": "main",
"index": 0
},
{
"node": "ac84877a-75cf-4ef2-bad1-8d0f444ecead",
"type": "main",
"index": 0
},
{
"node": "a5da65c5-db5a-4f9d-a6cf-228f081ffb3c",
"type": "main",
"index": 0
},
{
"node": "5b1f34b3-e675-46b1-a754-679080680058",
"type": "main",
"index": 0
},
{
"node": "0b3278a6-5793-4d70-8954-70562c43a3eb",
"type": "main",
"index": 0
},
{
"node": "28dd6fb1-a161-49ed-9c14-740e88e2195d",
"type": "main",
"index": 0
}
]
]
},
"d7d9bb31-6986-42e6-9f0c-7d7f00d66ee1": {
"main": [
[
{
"node": "a2e9d933-47d7-47f5-8d49-224860d8600a",
"type": "main",
"index": 0
},
{
"node": "702e8bc8-d8f0-4fb4-b44f-fd19479c8b03",
"type": "main",
"index": 0
},
{
"node": "d16b7829-59ca-45ca-a5ae-4e315168c96d",
"type": "main",
"index": 0
},
{
"node": "15bf5c3b-de07-412b-988c-f5c59fa7a06f",
"type": "main",
"index": 0
},
{
"node": "83fa487a-1a67-4059-9007-d5298d8bb105",
"type": "main",
"index": 0
},
{
"node": "7301ba32-ab0c-4c80-b041-cd398f7daa2c",
"type": "main",
"index": 0
}
]
]
},
"20e58706-035f-46ef-b235-78fe468875bc": {
"main": [
[
{
"node": "1675168b-97ab-4be4-92d2-734d075e2222",
"type": "main",
"index": 0
},
{
"node": "d1c2fcc7-65ac-446c-8f59-c4cd8ac7d795",
"type": "main",
"index": 0
},
{
"node": "df32e55c-2dbc-44d6-8161-f70db651cfcd",
"type": "main",
"index": 0
},
{
"node": "93a115f7-e876-43f0-8ecb-70a47a06f41c",
"type": "main",
"index": 0
},
{
"node": "17bf4e9f-7053-4a04-b439-3e23fe5cb7f9",
"type": "main",
"index": 0
},
{
"node": "d61db420-9def-4ec1-bf8a-94afeabda186",
"type": "main",
"index": 0
}
]
]
},
"91a05310-bd36-4ee0-8381-b3d16c3346be": {
"main": [
[
{
"node": "29121e2e-f6e2-4d42-8e5b-e8eea1e61ec8",
"type": "main",
"index": 0
}
]
]
},
"40fcbba9-489b-4452-baf8-9a41ef0f9b07": {
"main": [
[
{
"node": "9ec777b1-eb23-43b0-8bb3-726adcc3418f",
"type": "main",
"index": 0
}
]
]
},
"c4a718f8-f2d6-464b-8120-1e4067d760ad": {
"main": [
[
{
"node": "bbb81a2a-b1c4-4c1e-80e9-a4990c45fae8",
"type": "main",
"index": 0
}
]
]
},
"b372f57e-917a-42d2-964c-25a296ea982d": {
"main": [
[
{
"node": "61cb3bd7-60ba-4dcf-a080-146b7612a99b",
"type": "main",
"index": 0
}
]
]
},
"5ea4756f-a20a-444c-8471-57d209457823": {
"main": [
[
{
"node": "0a46ea7c-a85d-4fc6-b20c-7e65ab962ea6",
"type": "main",
"index": 0
}
]
]
},
"5b8c1049-bcf4-41d4-bba3-5f76e940bd3e": {
"main": [
[
{
"node": "5ea4756f-a20a-444c-8471-57d209457823",
"type": "main",
"index": 0
}
]
]
},
"6e9c7976-737b-4377-b412-633a1a67097b": {
"main": [
[
{
"node": "660dfcb4-ed63-4c53-806b-cba96c105fee",
"type": "main",
"index": 0
}
]
]
},
"a2e9d933-47d7-47f5-8d49-224860d8600a": {
"main": [
[
{
"node": "af471a36-1107-4ccd-be14-efa06ba27330",
"type": "main",
"index": 0
}
]
]
},
"1675168b-97ab-4be4-92d2-734d075e2222": {
"main": [
[
{
"node": "7940bc3f-c5f4-4b4b-b542-8737f17afbbf",
"type": "main",
"index": 0
}
]
]
}
}
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Finanzen, Künstliche Intelligenz
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Don Jayamaha Jr
@don-the-gem-dealerWith 12 years of experience as a Blockchain Strategist and Web3 Architect, I specialize in bridging the gap between traditional industries and decentralized technologies. My expertise spans tokenized assets, crypto payment integrations, and blockchain-driven market solutions.
Diesen Workflow teilen