{ "name": "Trading Bot v4 - TradingView to Drift", "nodes": [ { "parameters": { "path": "tradingview-signal", "responseMode": "responseNode", "options": {} }, "id": "webhook-trigger", "name": "TradingView Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 1, "position": [240, 300], "webhookId": "tradingview-signal" }, { "parameters": { "functionCode": "// Verify webhook secret\nconst secret = $input.item.json.query?.secret;\nconst expectedSecret = $env.TRADINGVIEW_WEBHOOK_SECRET || 'YOUR_SECRET_KEY';\n\nif (!secret || secret !== expectedSecret) {\n throw new Error('āŒ Invalid webhook secret');\n}\n\nconsole.log('āœ… Webhook secret verified');\n\nreturn {\n json: {\n verified: true,\n rawPayload: $input.item.json.body,\n timestamp: new Date().toISOString()\n }\n};" }, "id": "verify-secret", "name": "Verify Secret", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [460, 300] }, { "parameters": { "functionCode": "// Extract and normalize signal data\nconst body = $input.item.json.rawPayload || $input.item.json;\n\nconst signal = {\n action: body.action || 'buy',\n symbol: body.symbol || 'SOLUSDT',\n timeframe: body.timeframe || body.interval || '5',\n price: parseFloat(body.price || body.close) || 0,\n timestamp: body.timestamp || body.timenow || new Date().toISOString(),\n signalType: body.signal_type || (body.action === 'buy' ? 'buy' : 'sell'),\n strength: body.strength || 'moderate',\n strategy: body.strategy || '5min_scalp_v4'\n};\n\n// Normalize symbol to Drift market format\nif (signal.symbol.includes('SOL')) {\n signal.driftSymbol = 'SOL-PERP';\n} else if (signal.symbol.includes('BTC')) {\n signal.driftSymbol = 'BTC-PERP';\n} else if (signal.symbol.includes('ETH')) {\n signal.driftSymbol = 'ETH-PERP';\n} else {\n // Default to SOL if unknown\n signal.driftSymbol = 'SOL-PERP';\n}\n\n// Determine trading direction\nsignal.direction = (signal.action === 'buy' || signal.signalType === 'buy') ? 'long' : 'short';\n\n// Add metadata\nsignal.receivedAt = new Date().toISOString();\nsignal.source = 'tradingview';\n\nconsole.log('šŸ“Š Extracted signal:', JSON.stringify(signal, null, 2));\n\nreturn { json: signal };" }, "id": "extract-signal", "name": "Extract Signal Data", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [680, 300] }, { "parameters": { "method": "POST", "url": "={{ $env.TRADING_BOT_API_URL }}/api/trading/check-risk", "authentication": "predefinedCredentialType", "nodeCredentialType": "httpHeaderAuth", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" }, { "name": "Authorization", "value": "={{ 'Bearer ' + $env.API_SECRET_KEY }}" } ] }, "sendBody": true, "bodyParameters": { "parameters": [ { "name": "symbol", "value": "={{ $json.driftSymbol }}" }, { "name": "direction", "value": "={{ $json.direction }}" } ] }, "options": { "timeout": 10000 } }, "id": "check-risk", "name": "Check Risk Limits", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [900, 300] }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" }, "conditions": [ { "id": "risk-allowed", "leftValue": "={{ $json.allowed }}", "rightValue": true, "operator": { "type": "boolean", "operation": "equals" } } ], "combinator": "and" }, "options": {} }, "id": "if-risk-passed", "name": "Risk Check Passed?", "type": "n8n-nodes-base.if", "typeVersion": 2, "position": [1120, 300] }, { "parameters": { "method": "POST", "url": "={{ $env.TRADING_BOT_API_URL }}/api/trading/execute", "authentication": "predefinedCredentialType", "nodeCredentialType": "httpHeaderAuth", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" }, { "name": "Authorization", "value": "={{ 'Bearer ' + $env.API_SECRET_KEY }}" } ] }, "sendBody": true, "bodyParameters": { "parameters": [ { "name": "symbol", "value": "={{ $('Extract Signal Data').item.json.driftSymbol }}" }, { "name": "direction", "value": "={{ $('Extract Signal Data').item.json.direction }}" }, { "name": "timeframe", "value": "={{ $('Extract Signal Data').item.json.timeframe }}" }, { "name": "signalStrength", "value": "={{ $('Extract Signal Data').item.json.strength }}" }, { "name": "signalPrice", "value": "={{ $('Extract Signal Data').item.json.price }}" } ] }, "options": { "timeout": 30000 } }, "id": "execute-trade", "name": "Execute Trade", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [1340, 200] }, { "parameters": { "chatId": "={{ $env.TELEGRAM_CHAT_ID }}", "text": "=šŸŽÆ **Trade Executed!**\n\nšŸ“Š **Symbol:** {{ $json.symbol }}\nšŸ“ˆ **Direction:** {{ $json.direction.toUpperCase() }}\nšŸ’° **Entry:** ${{ $json.entryPrice }}\nšŸŽ² **Leverage:** 10x\nšŸ’µ **Position Size:** ${{ $json.positionSize }}\n\n**Targets:**\nšŸ”“ **Stop Loss:** ${{ $json.stopLoss }} (-{{ $json.stopLossPercent }}%)\n🟔 **TP1 (50%):** ${{ $json.takeProfit1 }} (+{{ $json.tp1Percent }}%)\n🟢 **TP2 (50%):** ${{ $json.takeProfit2 }} (+{{ $json.tp2Percent }}%)\n\nā±ļø **Time:** {{ $json.timestamp }}\nāœ… **Status:** Position opened\n\nšŸ“± Position ID: `{{ $json.positionId }}`", "additionalFields": { "parse_mode": "Markdown" } }, "id": "telegram-success", "name": "Telegram - Trade Success", "type": "n8n-nodes-base.telegram", "typeVersion": 1.1, "position": [1560, 100], "credentials": { "telegramApi": { "id": "telegram-credentials", "name": "Telegram Bot" } } }, { "parameters": { "chatId": "={{ $env.TELEGRAM_CHAT_ID }}", "text": "=āŒ **Trade Blocked**\n\nāš ļø **Reason:** {{ $('Check Risk Limits').item.json.reason }}\nšŸ“Š **Symbol:** {{ $('Extract Signal Data').item.json.driftSymbol }}\nšŸ“ˆ **Direction:** {{ $('Extract Signal Data').item.json.direction.toUpperCase() }}\nšŸ’° **Price:** ${{ $('Extract Signal Data').item.json.price }}\nā±ļø **Time:** {{ $('Extract Signal Data').item.json.timestamp }}\n\n**Risk Status:**\n{{ $('Check Risk Limits').item.json.details || 'Check dashboard for details' }}", "additionalFields": { "parse_mode": "Markdown" } }, "id": "telegram-blocked", "name": "Telegram - Trade Blocked", "type": "n8n-nodes-base.telegram", "typeVersion": 1.1, "position": [1340, 400], "credentials": { "telegramApi": { "id": "telegram-credentials", "name": "Telegram Bot" } } }, { "parameters": { "method": "POST", "url": "={{ $env.DISCORD_WEBHOOK_URL }}", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"embeds\": [{\n \"title\": \"šŸŽÆ New Trade Executed\",\n \"color\": {{ $json.direction === 'long' ? 5814783 : 15158332 }},\n \"fields\": [\n { \"name\": \"Symbol\", \"value\": \"{{ $json.symbol }}\", \"inline\": true },\n { \"name\": \"Direction\", \"value\": \"{{ $json.direction.toUpperCase() }}\", \"inline\": true },\n { \"name\": \"Leverage\", \"value\": \"10x\", \"inline\": true },\n { \"name\": \"Entry Price\", \"value\": \"${{ $json.entryPrice }}\", \"inline\": true },\n { \"name\": \"Position Size\", \"value\": \"${{ $json.positionSize }}\", \"inline\": true },\n { \"name\": \"Slippage\", \"value\": \"{{ $json.entrySlippage }}%\", \"inline\": true },\n { \"name\": \"Stop Loss\", \"value\": \"${{ $json.stopLoss }}\", \"inline\": true },\n { \"name\": \"Take Profit 1\", \"value\": \"${{ $json.takeProfit1 }}\", \"inline\": true },\n { \"name\": \"Take Profit 2\", \"value\": \"${{ $json.takeProfit2 }}\", \"inline\": true }\n ],\n \"footer\": {\n \"text\": \"Position ID: {{ $json.positionId }}\"\n },\n \"timestamp\": \"{{ $json.timestamp }}\"\n }]\n}", "options": {} }, "id": "discord-notification", "name": "Discord - Trade Success", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [1560, 200] }, { "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({\n success: $json.success !== undefined ? $json.success : true,\n positionId: $json.positionId || null,\n message: $json.message || 'Trade processed',\n timestamp: new Date().toISOString()\n}) }}" }, "id": "webhook-response", "name": "Webhook Response", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [1780, 300] } ], "pinData": {}, "connections": { "TradingView Webhook": { "main": [ [ { "node": "Verify Secret", "type": "main", "index": 0 } ] ] }, "Verify Secret": { "main": [ [ { "node": "Extract Signal Data", "type": "main", "index": 0 } ] ] }, "Extract Signal Data": { "main": [ [ { "node": "Check Risk Limits", "type": "main", "index": 0 } ] ] }, "Check Risk Limits": { "main": [ [ { "node": "Risk Check Passed?", "type": "main", "index": 0 } ] ] }, "Risk Check Passed?": { "main": [ [ { "node": "Execute Trade", "type": "main", "index": 0 } ], [ { "node": "Telegram - Trade Blocked", "type": "main", "index": 0 } ] ] }, "Execute Trade": { "main": [ [ { "node": "Telegram - Trade Success", "type": "main", "index": 0 }, { "node": "Discord - Trade Success", "type": "main", "index": 0 } ] ] }, "Telegram - Trade Success": { "main": [ [ { "node": "Webhook Response", "type": "main", "index": 0 } ] ] }, "Discord - Trade Success": { "main": [ [ { "node": "Webhook Response", "type": "main", "index": 0 } ] ] }, "Telegram - Trade Blocked": { "main": [ [ { "node": "Webhook Response", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1" }, "versionId": "trading-bot-v4-1.0.0", "id": "trading-bot-v4", "meta": { "instanceId": "your-n8n-instance-id" }, "tags": [ { "createdAt": "2025-10-23T00:00:00.000Z", "updatedAt": "2025-10-23T00:00:00.000Z", "id": "1", "name": "trading" }, { "createdAt": "2025-10-23T00:00:00.000Z", "updatedAt": "2025-10-23T00:00:00.000Z", "id": "2", "name": "automation" } ] }