Files
trading_bot_v3/n8n-workflow-v4.json
mindesbunister 1345a35680 feat: Complete Phase 2 - Autonomous Trading System
- Add Pyth Network price monitoring (WebSocket + polling fallback)
- Add Position Manager with automatic exit logic (TP1/TP2/SL)
- Implement dynamic stop-loss adjustment (breakeven + profit lock)
- Add real-time P&L tracking and multi-position support
- Create comprehensive test suite (3 test scripts)
- Add 5 detailed documentation files (2500+ lines)
- Update configuration to $50 position size for safe testing
- All Phase 2 features complete and tested

Core Components:
- v4/lib/pyth/price-monitor.ts - Real-time price monitoring
- v4/lib/trading/position-manager.ts - Autonomous position management
- v4/app/api/trading/positions/route.ts - Query positions endpoint
- v4/test-*.ts - Comprehensive testing suite

Documentation:
- PHASE_2_COMPLETE_REPORT.md - Implementation summary
- v4/PHASE_2_SUMMARY.md - Detailed feature overview
- v4/TESTING.md - Testing guide
- v4/QUICKREF_PHASE2.md - Quick reference
- install-phase2.sh - Automated installation script
2025-10-23 14:40:29 +02:00

367 lines
12 KiB
JSON
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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"
}
]
}