Krypto-RSI-Alarmierungssystem mit EODHD, Telegram und TradingView-Charts
Fortgeschritten
Dies ist ein Crypto Trading, Multimodal AI-Bereich Automatisierungsworkflow mit 15 Nodes. Hauptsächlich werden If, Set, Code, SplitOut, Telegram und andere Nodes verwendet. Ein Krypto-RSI-Alert-System mit Integration von EODHD, Telegram und TradingView-Charts
Voraussetzungen
- •Telegram Bot Token
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
Verwendete Nodes (15)
Kategorie
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
"meta": {
"instanceId": "c2b1f8c1d4a74a0cb8a1f1d3b7b0e7c1b9d2f5a8f3e44c9c93a1e2f4a6b7c8d9",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "m1",
"name": "Bei Klick auf 'Workflow ausführen'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-520,
-160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "note_overview",
"name": "Notiz – Übersicht",
"type": "n8n-nodes-base.stickyNote",
"position": [
-540,
-360
],
"parameters": {
"color": 6,
"width": 860,
"height": 260,
"content": "## Crypto RSI Alert Bot (overview)\n- Runs on a schedule or manual trigger.\n- Iterates a **watchlist** (BTC/ETH/SOL).\n- Fetches **intraday 1h** OHLCV from **EODHD** for each symbol.\n- Code node computes **Wilder's RSI(14)** and detects **30/70** crossings.\n- On signal, sends a **Telegram** alert (HTML) + **View chart** button (TradingView BINANCE/USD).\n\nEnv vars required:\n- `EODHD_TOKEN`\n- `TELEGRAM_CHAT_ID`"
},
"typeVersion": 1
},
{
"id": "set1",
"name": "Felder bearbeiten (Watchlist)",
"type": "n8n-nodes-base.set",
"position": [
-300,
-160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "sym_arr",
"name": "symbol",
"type": "array",
"value": "[\"BTC-USD.CC\",\"ETH-USD.CC\",\"SOL-USD.CC\"]"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "note_watchlist",
"name": "Notiz – Watchlist",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-300
],
"parameters": {
"color": 6,
"width": 560,
"height": 160,
"content": "### Edit Fields (watchlist)\n- Defines the **symbol array**.\n- Make sure the field type is **Array** (String[]), not a single String.\n- Example output: `{ symbol: [\"BTC-USD.CC\",\"ETH-USD.CC\",\"SOL-USD.CC\"] }`"
},
"typeVersion": 1
},
{
"id": "split_out",
"name": "Aufteilen",
"type": "n8n-nodes-base.splitOut",
"position": [
-80,
-160
],
"parameters": {
"options": {},
"fieldToSplitOut": "symbol"
},
"typeVersion": 1
},
{
"id": "note_split",
"name": "Notiz – Aufteilen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-100,
-300
],
"parameters": {
"color": 6,
"width": 520,
"height": 150,
"content": "### Split Out\n- Explodes the array into **one item per symbol**.\n- Input: 1 item with array → Output: N items like `{ symbol: \"BTC-USD.CC\" }`."
},
"typeVersion": 1
},
{
"id": "loop",
"name": "Über Elemente iterieren",
"type": "n8n-nodes-base.splitInBatches",
"position": [
140,
-160
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "note_loop",
"name": "Notiz – Schleife",
"type": "n8n-nodes-base.stickyNote",
"position": [
120,
-300
],
"parameters": {
"color": 6,
"width": 560,
"height": 120,
"content": "### Loop Over Items\n- Processes **one symbol per pass** to avoid mixing BTC/ETH/SOL candles.\n- Wiring: **Loop → HTTP → Code → back to Loop**. **Done → IF**."
},
"typeVersion": 1
},
{
"id": "http",
"name": "HTTP Anfrage (EODHD Intraday 1h)",
"type": "n8n-nodes-base.httpRequest",
"position": [
360,
-260
],
"parameters": {
"url": "=https://eodhd.com/api/intraday/{{ $json.symbol }}",
"method": "GET",
"options": {
"redirect": {
"redirect": {}
},
"response": {
"response": {}
},
"splitIntoItems": true
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "interval",
"value": "1h"
},
{
"name": "fmt",
"value": "json"
},
{
"name": "api_token",
"value": "={{ $env.EODHD_TOKEN }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "note_http",
"name": "Notiz – HTTP",
"type": "n8n-nodes-base.stickyNote",
"position": [
340,
-420
],
"parameters": {
"color": 6,
"width": 560,
"height": 160,
"content": "### HTTP (EODHD)\n- Fetches **intraday 1h OHLCV** for current symbol.\n- Token via env var `EODHD_TOKEN` → no secret in JSON.\n- **Split Into Items** enabled: 1 candle = 1 item (~2–3k items)."
},
"typeVersion": 1
},
{
"id": "code",
"name": "Code (RSI + Nachricht)",
"type": "n8n-nodes-base.code",
"position": [
580,
-260
],
"parameters": {
"jsCode": "// n8n Code node — Run Once for All Items\\n// Computes RSI(14) (Wilder) on 1h candles and raises 30/70 cross alerts.\\n\\nconst PERIOD = 14;\\nconst OVERBOUGHT = 70;\\nconst OVERSOLD = 30;\\n\\n// Collect ALL candles from the HTTP node (1 item = 1 candle)\\nconst inputItems = $input.all();\\nlet candles = [];\\nfor (const it of inputItems) {\\n if (Array.isArray(it.json)) candles.push(...it.json);\\n else candles.push(it.json);\\n}\\n\\n// Normalize + sort by time (prefer numeric timestamp, fallback to datetime)\\ncandles = candles\\n .filter(r => r && r.close !== undefined)\\n .map(r => ({\\n t: (Number.isFinite(+r.timestamp) ? +r.timestamp\\n : (typeof r.datetime === 'number' ? r.datetime : Date.parse(r.datetime)/1000)),\\n close: +r.close\\n }))\\n .filter(r => Number.isFinite(r.t) && Number.isFinite(r.close))\\n .sort((a,b) => a.t - b.t);\\n\\nif (candles.length < PERIOD + 2) {\\n return [{ json: { error: 'Not enough candles for RSI', count: candles.length } }];\\n}\\n\\nconst closes = candles.map(c => c.close);\\n\\n// Wilder RSI (full series)\\nfunction rsiSeries(values, period = 14) {\\n const deltas = [];\\n for (let i = 1; i < values.length; i++) deltas.push(values[i] - values[i - 1]);\\n let gain = 0, loss = 0;\\n for (let i = 0; i < period; i++) { const d = deltas[i]; if (d >= 0) gain += d; else loss -= d; }\\n let avgGain = gain / period; let avgLoss = loss / period;\\n const rsis = new Array(values.length).fill(null);\\n rsis[period] = avgLoss === 0 ? 100 : 100 - (100 / (1 + (avgGain / avgLoss)));\\n for (let i = period + 1; i < values.length; i++) {\\n const d = deltas[i - 1];\\n const up = Math.max(d, 0);\\n const down = Math.max(-d, 0);\\n avgGain = ((avgGain * (period - 1)) + up) / period;\\n avgLoss = ((avgLoss * (period - 1)) + down) / period;\\n const rs = avgLoss === 0 ? Infinity : (avgGain / avgLoss);\\n rsis[i] = 100 - (100 / (1 + rs));\\n }\\n return rsis;\\n}\\n\\nconst rsis = rsiSeries(closes, PERIOD);\\nconst lastIdx = rsis.length - 1;\\nconst rsiNow = +rsis[lastIdx].toFixed(1);\\nconst rsiPrev = +rsis[lastIdx - 1].toFixed(1);\\nconst lastClose = +closes[lastIdx].toFixed(2);\\nconst lastTs = candles[lastIdx].t;\\n\\n// Signals\\nlet signal = null;\\nif (rsiPrev > OVERSOLD && rsiNow <= OVERSOLD) signal = 'enter_oversold';\\nelse if (rsiPrev < OVERBOUGHT && rsiNow >= OVERBOUGHT) signal = 'enter_overbought';\\nelse if (rsiPrev <= OVERSOLD && rsiNow > OVERSOLD) signal = 'exit_oversold';\\nelse if (rsiPrev >= OVERBOUGHT && rsiNow < OVERBOUGHT) signal = 'exit_overbought';\\n\\n// ======= TEST TOGGLE (set true only to test Telegram delivery) =======\\nconst FORCE_ALERT = false; // keep false in production\\nconst FORCE_SIGNAL = 'enter_overbought'; // 'enter_oversold' | 'exit_oversold' | 'exit_overbought'\\nif (FORCE_ALERT) signal = FORCE_SIGNAL;\\n// =====================================================================\\n\\n// Current symbol from the loop item (fallback to input $json)\\nconst symbol = $('Split Out')?.item?.json?.symbol || $json.symbol || 'UNKNOWN';\\n\\nconst TF = '1h';\\nconst fmt = (n, d=2) => Number(n).toLocaleString('en-US',{minimumFractionDigits:d, maximumFractionDigits:d});\\nconst tsUTC = (ts) => new Date(ts*1000).toISOString().replace('T',' ').slice(0,16) + ' UTC';\\n\\nlet emoji = '🔔', headline = '';\\nif (signal === 'enter_oversold') { emoji='🔻'; headline = `enters <u>oversold</u> (RSI ${rsiNow} ≤ 30)`; }\\nelse if (signal === 'enter_overbought') { emoji='🚀'; headline = `enters <u>overbought</u> (RSI ${rsiNow} ≥ 70)`; }\\nelse if (signal === 'exit_oversold') { emoji='✅'; headline = `exits <u>oversold</u> (RSI ${rsiNow})`; }\\nelse if (signal === 'exit_overbought') { emoji='✅'; headline = `exits <u>overbought</u> (RSI ${rsiNow})`; }\\n\\nconst alertTextHtml = signal ? (\\n `${emoji} <b>${symbol}</b> ${headline}\\n` +\\n `Price: <b>$${fmt(lastClose)}</b> · TF: <b>${TF}</b> · ${tsUTC(lastTs)}\\n` +\\n `RSI: <b>${rsiPrev} → ${rsiNow}</b> (30/70)\\n` +\\n `— <i>RSI Heatwave</i>`\\n) : null;\\n\\nconst alertText = signal ? `${symbol} | ${headline.replace(/<[^>]*>/g,'')} | Price $${fmt(lastClose)} · TF ${TF} · ${tsUTC(lastTs)} | RSI ${rsiPrev}→${rsiNow}` : null;\\n\\n// TradingView link (BINANCE + USD) from EODHD symbol (e.g., BTC-USD.CC → BTCUSD)\\nconst rawSymbol = $('Split Out')?.item?.json?.symbol ?? $json.symbol ?? symbol;\\nconst sym = Array.isArray(rawSymbol) ? rawSymbol[0] : rawSymbol; \\nconst base = String(sym).split('-')[0].toUpperCase();\\nconst tradingViewUrl = `https://www.tradingview.com/symbols/${base}USD/?exchange=BINANCE`;\\n\\nreturn [{ json: { symbol, rsi: rsiNow, rsiPrev, period: PERIOD, lastClose, signal, timestamp: lastTs, alertText, alertTextHtml, tradingViewUrl } }];"
},
"typeVersion": 2
},
{
"id": "note_code",
"name": "Notiz – Code",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
-420
],
"parameters": {
"color": 6,
"width": 560,
"height": 170,
"content": "### Code (RSI + message)\n- Sorts candles, computes **RSI(14)** (Wilder), detects 30/70 crossings.\n- Builds HTML message + TradingView URL (BINANCE/USD).\n- Testing: set `FORCE_ALERT = true`, then back to `false`."
},
"typeVersion": 1
},
{
"id": "if",
"name": "IF (Signal vorhanden?)",
"type": "n8n-nodes-base.if",
"position": [
140,
40
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond1",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.signal }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "tg",
"name": "Textnachricht senden",
"type": "n8n-nodes-base.telegram",
"position": [
360,
40
],
"parameters": {
"text": "={{ $json.alertTextHtml }}",
"chatId": "={{ $env.TELEGRAM_CHAT_ID }}",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "View chart",
"additionalFields": {
"url": "={{ $json.tradingViewUrl }}"
}
}
]
}
}
]
},
"additionalFields": {
"parse_mode": "HTML",
"disable_web_page_preview": true
}
},
"credentials": {
"telegramApi": {
"id": "REPLACE_WITH_YOUR_TELEGRAM_CRED_ID",
"name": "Telegram account"
}
},
"typeVersion": 1.2
},
{
"id": "note_tg",
"name": "Notiz – Telegram",
"type": "n8n-nodes-base.stickyNote",
"position": [
340,
180
],
"parameters": {
"color": 6,
"width": 560,
"height": 140,
"content": "### Telegram (delivery)\n- Parse Mode: **HTML**.\n- Text: `{{$json.alertTextHtml}}`.\n- Button: **View chart** → `{{$json.tradingViewUrl}}`.\n- Chat ID via env var `TELEGRAM_CHAT_ID`.\n- Bot token stays in Credentials."
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"split_out": {
"main": [
[
{
"node": "loop",
"type": "main",
"index": 0
}
]
]
},
"loop": {
"main": [
[
{
"node": "if",
"type": "main",
"index": 0
}
],
[
{
"node": "http",
"type": "main",
"index": 0
}
]
]
},
"if": {
"main": [
[
{
"node": "tg",
"type": "main",
"index": 0
}
]
]
},
"code": {
"main": [
[
{
"node": "loop",
"type": "main",
"index": 0
}
]
]
},
"set1": {
"main": [
[
{
"node": "split_out",
"type": "main",
"index": 0
}
]
]
},
"http": {
"main": [
[
{
"node": "code",
"type": "main",
"index": 0
}
]
]
},
"m1": {
"main": [
[
{
"node": "set1",
"type": "main",
"index": 0
}
]
]
}
}
}Häufig gestellte Fragen
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?
Fortgeschritten - Krypto-Handel, Multimodales KI
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
InhaltGenerator v3
If
Set
Code
+
If
Set
Code
144 NodesJay Emp0
Content-Erstellung
Freelancer.com-Automatischer Bewerber (mit Telegram-Besapproval und AI-Vorschlägen)
Freelancer.com-Automatischer Auktionsbote mit Telegram- genehmigung und KI-Antragsgenerierung
If
Set
Split Out
+
If
Set
Split Out
26 NodesMohamed Abdelwahab
Lead-Pflege
Printify-Automatisierung - Titel- und Beschreibungsaktualisierung - AlexK1919
Automatisierte Erstellung von SEO-Produkttiteln und -beschreibungen für Printify mit GPT-4o-mini
If
Set
Code
+
If
Set
Code
26 NodesAmit Mehta
Content-Erstellung
Von Sitemap-Crawling zum Vektorspeicher: Erstellung eines effizienten RAG-Workflows
Sitemap-Crawling bis zur Vektorspeicherung: Erstellung effizienter RAG-Workflows
If
Set
Xml
+
If
Set
Xml
40 NodesMariela Slavenova
Content-Erstellung
Automatisierte Datenerfassung von Leadfeeder und Apollo.io
Lead-Enrichment-Pipeline: von Leadfeeder über Apollo zu Google Sheets
If
Set
Code
+
If
Set
Code
23 NodesKhairul Muhtadin
Lead-Generierung
Aktienanalyse-Vorlage
Erstellen von Aktienmarkteinblicken durch Kombination von technischer Analyse, KI und Telegram
If
Set
Code
+
If
Set
Code
25 NodesSergey Skorobogatov
Krypto-Handel
Workflow-Informationen
Schwierigkeitsgrad
Fortgeschritten
Anzahl der Nodes15
Kategorie2
Node-Typen9
Autor
Kevin
@pythonia-kevinExterne Links
Auf n8n.io ansehen →
Diesen Workflow teilen