docs: Update n8n MCP token + Add comprehensive workflow documentation

- Updated MCP Bearer token in copilot-instructions.md (new token ending ...SQbRcoBo)
- Created docs/N8N_WORKFLOW_DOCUMENTATION.md with complete Money Machine workflow docs
- Smart Entry bypass for v11.2+ signals with indicatorScore >= 90
- Money_Machine.json formatting cleanup

Files changed:
- .github/copilot-instructions.md: MCP token update
- docs/N8N_WORKFLOW_DOCUMENTATION.md: NEW comprehensive n8n docs
- app/api/trading/execute/route.ts: Smart Entry bypass for high-quality signals
- workflows/trading/Money_Machine.json: Telegram message formatting fixes
This commit is contained in:
mindesbunister
2026-01-01 15:47:33 +01:00
parent 26ddd177b3
commit 184b8f8a5b
6 changed files with 1784 additions and 7 deletions

View File

@@ -6647,7 +6647,7 @@ CREATE TABLE strategies (
"--streamableHttp",
"https://flow.egonetix.de/mcp-server/http",
"--header",
"authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NzIxYWQ0OC03NDFjLTRmMDMtOWUxNS0zNDc4MTNiZDJhNmUiLCJpc3MiOiJuOG4iLCJhdWQiOiJtY3Atc2VydmVyLWFwaSIsImp0aSI6ImUyYmIwNDgwLTIyYjMtNDEyZi05MTg4LTY3ZjYwYWVmY2EzYSIsImlhdCI6MTc2NTY0MTAyNn0.Ci0KOuSXgO4LlO6Ei7RN8C5t41HM0yDbeiYBtUQaWU4"
"authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NzIxYWQ0OC03NDFjLTRmMDMtOWUxNS0zNDc4MTNiZDJhNmUiLCJpc3MiOiJuOG4iLCJhdWQiOiJtY3Atc2VydmVyLWFwaSIsImp0aSI6IjQ2MTQ0ZTNjLWEwMjctNDBiMS1iNTA0LTBhMGRlOGMzNWY4MiIsImlhdCI6MTc2NzI3NzkyOX0.49H7R-GijkrI-Ygthxjq7XowEVkFP8GiN2_SQbRcoBo"
]
}
}

View File

@@ -539,8 +539,17 @@ export async function POST(request: NextRequest): Promise<NextResponse<ExecuteTr
console.log(` Total position: $${positionSizeUSD}`)
// 🎯 SMART ENTRY TIMING - Check if we should wait for better entry (Phase 2 - Nov 27, 2025)
// BYPASS (Dec 27, 2025): Skip Smart Entry for v11.2+ signals with high indicator scores
// Rationale: v11.2 indicator already filters to profitable setups (2.617 PF backtest)
// Smart Entry queue adds delay without improving already-high-quality signals
const skipSmartEntry = typeof body.indicatorScore === 'number' && body.indicatorScore >= 90
if (skipSmartEntry) {
console.log(`🚀 SMART ENTRY BYPASS: indicatorScore ${body.indicatorScore} >= 90, executing immediately`)
}
const smartEntryTimer = getSmartEntryTimer()
if (smartEntryTimer.isEnabled() && body.signalPrice) {
if (smartEntryTimer.isEnabled() && body.signalPrice && !skipSmartEntry) {
console.log(`🎯 Smart Entry: Evaluating entry timing...`)
// CRITICAL FIX (Dec 3, 2025): Use current market price, not body.signalPrice

View File

@@ -0,0 +1,390 @@
# n8n Workflow Documentation - Money Machine
**Last Updated:** January 1, 2025
**Workflow ID:** gUDqTiHyHSfRUXv6
**Status:** ✅ ACTIVE in Production
## Overview
The Money Machine workflow is the core automation pipeline connecting TradingView alerts to the Trading Bot v4 system. It handles signal parsing, risk validation, trade execution, and Telegram notifications.
---
## n8n Access Credentials
### REST API (for programmatic access)
```bash
# API Endpoint
https://flow.egonetix.de/api/v1/
# API Key (X-N8N-API-KEY header)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NzIxYWQ0OC03NDFjLTRmMDMtOWUxNS0zNDc4MTNiZDJhNmUiLCJpc3MiOiJuOG4iLCJhdWQiOiJwdWJsaWMtYXBpIiwiaWF0IjoxNzY1NjQxNTgzfQ.qcDc8W21GqG4jlfju3IOYlntAiBBfDCfA9tZh4TBNHQ
```
### MCP Server (for AI/IDE integration)
```json
{
"mcpServers": {
"n8n-mcp": {
"command": "npx",
"args": [
"-y",
"supergateway",
"--streamableHttp",
"https://flow.egonetix.de/mcp-server/http",
"--header",
"authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NzIxYWQ0OC03NDFjLTRmMDMtOWUxNS0zNDc4MTNiZDJhNmUiLCJpc3MiOiJuOG4iLCJhdWQiOiJtY3Atc2VydmVyLWFwaSIsImp0aSI6IjQ2MTQ0ZTNjLWEwMjctNDBiMS1iNTA0LTBhMGRlOGMzNWY4MiIsImlhdCI6MTc2NzI3NzkyOX0.49H7R-GijkrI-Ygthxjq7XowEVkFP8GiN2_SQbRcoBo"
]
}
}
}
```
### Example API Calls
```bash
# List all workflows
curl -s -X GET "https://flow.egonetix.de/api/v1/workflows" \
-H "X-N8N-API-KEY: <API_KEY>"
# Get specific workflow
curl -s -X GET "https://flow.egonetix.de/api/v1/workflows/gUDqTiHyHSfRUXv6" \
-H "X-N8N-API-KEY: <API_KEY>"
# Get workflow executions
curl -s -X GET "https://flow.egonetix.de/api/v1/executions?workflowId=gUDqTiHyHSfRUXv6" \
-H "X-N8N-API-KEY: <API_KEY>"
```
---
## Money Machine Workflow Structure
### Workflow Metadata
| Property | Value |
|----------|-------|
| ID | gUDqTiHyHSfRUXv6 |
| Name | Money Machine |
| Active | ✅ true |
| Node Count | 12 |
| Version ID | 955bd768-0c3b-490a-9c6b-5c01bc2f6d44 |
### Node List (12 nodes)
1. **Webhook** - Entry point for TradingView alerts
2. **Parse Signal Enhanced** - JavaScript code to parse signal format
3. **Check Risk1** - HTTP POST to `/api/trading/check-risk`
4. **Risk Passed?** - Boolean condition on `allowed` field
5. **Execute Trade1** - HTTP POST to `/api/trading/execute`
6. **Trade Success?** - Boolean condition on `success` field
7. **Format Success** - Format success message for Telegram
8. **Format Error** - Format error message for Telegram
9. **Format Risk** - Format blocked trade message
10. **Telegram Success** - Send success notification
11. **Telegram Error** - Send error notification
12. **Telegram Risk** - Send blocked trade notification
---
## Signal Flow
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ MONEY MACHINE WORKFLOW │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ TradingView Alert │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Webhook │ POST /webhook/tradingview-bot-v4 │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Parse Signal Enhanced │ Extract: symbol, direction, timeframe, │
│ │ (JavaScript Code) │ atr, adx, rsi, volumeRatio, pricePosition, │
│ └──────────┬──────────────┘ indicatorVersion, indicatorScore │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Check Risk1 │ POST http://10.0.0.48:3001/api/trading/check-risk │
│ │ (HTTP Request) │ Body: {symbol, direction, timeframe, metrics...} │
│ └──────────┬──────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ TRUE: allowed=true │
│ │ Risk Passed? ├──────────────────────────┐ │
│ │ (IF Condition) │ │ │
│ └──────────┬──────────────┘ │ │
│ │ FALSE: allowed=false │ │
│ ▼ ▼ │
│ ┌───────────────┐ ┌────────────────────────────┐ │
│ │ Format Risk │ │ Execute Trade1 │ │
│ │ (Set Node) │ │ POST /api/trading/execute │ │
│ └───────┬───────┘ │ Timeout: 120s │ │
│ │ └────────────┬───────────────┘ │
│ ▼ │ │
│ ┌────────────────────┐ ▼ │
│ │ Check Skip │ ┌──────────────────────────┐ │
│ │ Notification │ │ Trade Success? │ │
│ └───────┬────────────┘ │ (IF Condition) │ │
│ │ Skip=false └─────┬──────────┬─────────┘ │
│ ▼ TRUE │ │ FALSE │
│ ┌───────────────┐ ┌──────────────┘ └────────────┐ │
│ │ Telegram Risk │ ▼ ▼ │
│ └───────────────┘ ┌────────────────┐ ┌────────────────┐ │
│ │ Format Success │ │ Format Error │ │
│ └───────┬────────┘ └───────┬────────┘ │
│ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Telegram Success │ │ Telegram Error │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
---
## Node Details
### 1. Webhook
- **Type:** n8n-nodes-base.webhook
- **Path:** `tradingview-bot-v4`
- **Full URL:** `https://flow.egonetix.de/webhook/tradingview-bot-v4`
- **Method:** POST
- **Purpose:** Entry point for all TradingView alerts
### 2. Parse Signal Enhanced
- **Type:** n8n-nodes-base.code (JavaScript)
- **Purpose:** Parse TradingView alert message into structured data
**Input Format:**
```
SOL buy 5 | ATR:0.65 | ADX:14.3 | RSI:51.3 | VOL:0.87 | POS:59.3 | IND:v8 | SCORE:100
```
**Output Fields:**
```javascript
{
rawMessage: "original message",
symbol: "SOL-PERP", // Extracted and normalized
direction: "long", // "buy" → "long", "sell/short" → "short"
timeframe: "5", // Chart timeframe
atr: 0.65, // Average True Range
adx: 14.3, // ADX trend strength
rsi: 51.3, // Relative Strength Index
volumeRatio: 0.87, // Volume vs 20-period SMA
pricePosition: 59.3, // Price position in 100-bar range (0-100)
indicatorVersion: "v8", // TradingView indicator version
indicatorScore: 100 // Quality score from indicator (optional)
}
```
**Symbol Mapping:**
- `SOL``SOL-PERP`
- `BTC``BTC-PERP`
- `ETH``ETH-PERP`
- `FARTCOIN` or `FART``FARTCOIN-PERP`
### 3. Check Risk1
- **Type:** n8n-nodes-base.httpRequest
- **Method:** POST
- **URL:** `http://10.0.0.48:3001/api/trading/check-risk`
- **Authentication:** Bearer token
**Request Body:**
```json
{
"symbol": "SOL-PERP",
"direction": "long",
"timeframe": "5",
"atr": 0.65,
"adx": 14.3,
"rsi": 51.3,
"volumeRatio": 0.87,
"pricePosition": 59.3
}
```
**Expected Response:**
```json
{
"allowed": true,
"reason": "signal passed quality check",
"qualityScore": 95
}
```
### 4. Risk Passed? (IF Condition)
- **Type:** n8n-nodes-base.if
- **Condition:** `{{ $json.allowed }}` equals `true`
- **TRUE branch:** → Execute Trade1
- **FALSE branch:** → Format Risk
### 5. Execute Trade1
- **Type:** n8n-nodes-base.httpRequest
- **Method:** POST
- **URL:** `http://10.0.0.48:3001/api/trading/execute`
- **Timeout:** 120,000ms (2 minutes)
- **Authentication:** Bearer token
**Request Body:**
```json
{
"symbol": "{{ $('Parse Signal Enhanced').item.json.symbol }}",
"direction": "{{ $('Parse Signal Enhanced').item.json.direction }}",
"timeframe": "{{ $('Parse Signal Enhanced').item.json.timeframe }}",
"atr": {{ $('Parse Signal Enhanced').item.json.atr }},
"adx": {{ $('Parse Signal Enhanced').item.json.adx }},
"rsi": {{ $('Parse Signal Enhanced').item.json.rsi }},
"volumeRatio": {{ $('Parse Signal Enhanced').item.json.volumeRatio }},
"pricePosition": {{ $('Parse Signal Enhanced').item.json.pricePosition }},
"indicatorVersion": "{{ $('Parse Signal Enhanced').item.json.indicatorVersion }}",
"signalPrice": {{ $('Parse Signal Enhanced').item.json.pricePosition }},
"indicatorScore": {{ $('Parse Signal Enhanced').item.json.indicatorScore || 'null' }}
}
```
### 6. Trade Success? (IF Condition)
- **Type:** n8n-nodes-base.if
- **Condition:** `{{ $json.success }}` equals `true`
- **TRUE branch:** → Format Success
- **FALSE branch:** → Format Error
### 7-9. Format Nodes (Set)
Format messages for Telegram notifications based on trade outcome.
### 10-12. Telegram Nodes
- **Type:** n8n-nodes-base.telegram
- **Chat ID:** 579304651
- **Credential:** "Telegram account" (ID: Csk5cg4HtaSqP5jJ)
---
## Internal API Configuration
### Bot API Base URL
```
http://10.0.0.48:3001
```
### API Endpoints Used
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/api/trading/check-risk` | POST | Validate signal quality before execution |
| `/api/trading/execute` | POST | Execute trade on Drift Protocol |
### Authentication Token
```
Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb
```
---
## Other n8n Workflows
Besides Money Machine, the following workflows exist on the n8n instance:
| ID | Name | Status |
|----|------|--------|
| gUDqTiHyHSfRUXv6 | Money Machine | ✅ Active |
| Various | Telegram Bot with AI | Active |
| Various | Telegram Bot Simple (x2) | Active |
| Various | Telegram Router Direct (x2) | Active |
---
## Local Workflow Files
Location: `/home/icke/traderv4/workflows/trading/`
| File | Purpose |
|------|---------|
| `Money_Machine.json` | Main workflow (current) |
| `Money_Machine_backup.json` | Backup copy |
| `Money_Machine_backup_2.json` | Secondary backup |
| `parse_signal_enhanced.json` | Standalone signal parser |
| `market_data_forwarder.json` | Market data handling |
| `market_data_handler.json` | Market data processing |
---
## Indicator Score Bypass (v11.2+)
As of Dec 26, 2025, the v11.2 indicator sends `SCORE:100` in alerts to bypass bot quality scoring:
**Signal Format:**
```
SOL buy 5 | ATR:0.65 | ADX:14.3 | RSI:51.3 | VOL:0.87 | POS:59.3 | IND:v11.2 | SCORE:100
```
**Parse Logic (added to Parse Signal Enhanced):**
```javascript
const scoreMatch = body.match(/SCORE:(\d+)/);
const indicatorScore = scoreMatch ? parseInt(scoreMatch[1]) : null;
```
**Bot Behavior:**
- If `indicatorScore >= 90`: Bypasses quality check entirely
- Rationale: v11.2 indicator already filters to profitable setups (PF 2.617)
---
## Troubleshooting
### Common Issues
1. **Signal not executing:**
- Check Risk1 response - verify `allowed: true`
- Check quality score meets threshold (LONG ≥90, SHORT ≥80)
- Verify symbol is enabled in bot config
2. **Telegram notification missing:**
- Check "Check Skip Notification" node conditions
- Verify Telegram credentials still valid
3. **Timeout on Execute Trade1:**
- 120s timeout may be insufficient for slow Drift responses
- Check Drift RPC endpoint health
### Debug Steps
```bash
# Get recent executions
curl -s -X GET "https://flow.egonetix.de/api/v1/executions?workflowId=gUDqTiHyHSfRUXv6&limit=5" \
-H "X-N8N-API-KEY: <API_KEY>" | jq '.[].status'
# Check workflow is active
curl -s -X GET "https://flow.egonetix.de/api/v1/workflows/gUDqTiHyHSfRUXv6" \
-H "X-N8N-API-KEY: <API_KEY>" | jq '.active'
```
---
## Modification Guide
### To Update Workflow via API:
```bash
# Export modified workflow JSON, then:
curl -X PUT "https://flow.egonetix.de/api/v1/workflows/gUDqTiHyHSfRUXv6" \
-H "X-N8N-API-KEY: <API_KEY>" \
-H "Content-Type: application/json" \
-d @Money_Machine.json
```
### To Update via UI:
1. Open https://flow.egonetix.de
2. Navigate to Money Machine workflow
3. Edit nodes as needed
4. Save workflow
5. Export updated JSON to `/home/icke/traderv4/workflows/trading/Money_Machine.json`
---
## Version History
| Date | Change | Commit |
|------|--------|--------|
| Dec 26, 2025 | Added indicatorScore parsing for v11.2 bypass | ba1fe44 |
| Dec 7, 2025 | Fixed symbol normalization for FARTCOIN | - |
| Nov 27, 2025 | Added MA crossover detection flags | - |
| Nov 19, 2025 | Enhanced timeframe parsing | - |

View File

@@ -19,7 +19,7 @@
},
{
"parameters": {
"jsCode": "// Get the body - it might be a string or nested in an object\nlet body = $json.body || $json.query?.body || JSON.stringify($json);\n\n// If body is an object, stringify it\nif (typeof body === 'object') {\n body = JSON.stringify(body);\n}\n\n// Forward market data payloads directly to /api/trading/market-data and stop workflow\ntry {\n const parsed = JSON.parse(body);\n const action = parsed?.action?.toLowerCase?.() || '';\n if (action.startsWith('market_data')) {\n await fetch('http://10.0.0.48:3001/api/trading/market-data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(parsed),\n });\n return []; // Halt further nodes (no Telegram/risk)\n }\n} catch (err) {\n // Body isn't JSON, keep processing\n}\nif (/market_data/i.test(body)) {\n // Fallback: drop unknown market_data text payloads\n return [];\n}\n\n// Parse basic signal (existing logic)\nconst symbolMatch = body.match(/\\b(SOL|BTC|ETH)\\b/i);\nconst symbol = symbolMatch ? symbolMatch[1].toUpperCase() + '-PERP' : 'SOL-PERP';\n\nconst direction = body.match(/\\b(sell|short)\\b/i) ? 'short' : 'long';\n\n// Enhanced timeframe extraction supporting multiple formats:\n// - \"buy 5\" \u2192 \"5\"\n// - \"buy 15\" \u2192 \"15\"\n// - \"buy 60\" or \"buy 1h\" \u2192 \"60\"\n// - \"buy 240\" or \"buy 4h\" \u2192 \"240\"\n// - \"buy D\" or \"buy 1d\" \u2192 \"D\"\n// - \"buy W\" \u2192 \"W\"\nconst timeframeMatch = body.match(/\\b(buy|sell)\\s+(\\d+|D|W|M|1h|4h|1d)\\b/i);\nlet timeframe = '5'; // Default to 5min\n\nif (timeframeMatch) {\n const tf = timeframeMatch[2];\n // Convert hour/day notation to minutes\n if (tf === '1h' || tf === '60') {\n timeframe = '60';\n } else if (tf === '4h' || tf === '240') {\n timeframe = '240';\n } else if (tf === '1d' || tf.toUpperCase() === 'D') {\n timeframe = 'D';\n } else if (tf.toUpperCase() === 'W') {\n timeframe = 'W';\n } else if (tf.toUpperCase() === 'M') {\n timeframe = 'M';\n } else {\n timeframe = tf;\n }\n}\n\n// Parse new context metrics from enhanced format:\n// \"SOLT.P buy 15 | ATR:0.65 | ADX:14.3 | RSI:51.3 | VOL:0.87 | POS:59.3 | IND:v8\"\nconst atrMatch = body.match(/ATR:([\\d.]+)/);\nconst atr = atrMatch ? parseFloat(atrMatch[1]) : 0;\n\nconst adxMatch = body.match(/ADX:([\\d.]+)/);\nconst adx = adxMatch ? parseFloat(adxMatch[1]) : 0;\n\nconst rsiMatch = body.match(/RSI:([\\d.]+)/);\nconst rsi = rsiMatch ? parseFloat(rsiMatch[1]) : 0;\n\nconst volumeMatch = body.match(/VOL:([\\d.]+)/);\nconst volumeRatio = volumeMatch ? parseFloat(volumeMatch[1]) : 0;\n\nconst pricePositionMatch = body.match(/POS:([\\d.]+)/);\nconst pricePosition = pricePositionMatch ? parseFloat(pricePositionMatch[1]) : 0;\n\n// Parse indicator version (optional, backward compatible)\nconst indicatorVersionMatch = body.match(/IND:(v\\d+)/i);\nconst indicatorVersion = indicatorVersionMatch ? indicatorVersionMatch[1] : 'v8';\n\nreturn {\n rawMessage: body,\n symbol,\n direction,\n timeframe,\n // Context fields\n atr,\n adx,\n rsi,\n volumeRatio,\n pricePosition,\n // Version tracking (defaults to v8 for backward compatibility)\n indicatorVersion\n};"
"jsCode": "// Get the body - it might be a string or nested in an object\nlet body = $json.body || $json.query?.body || JSON.stringify($json);\n\n// If body is an object, stringify it\nif (typeof body === 'object') {\n body = JSON.stringify(body);\n}\n\n// Forward market data payloads directly to /api/trading/market-data and stop workflow\ntry {\n const parsed = JSON.parse(body);\n const action = parsed?.action?.toLowerCase?.() || '';\n if (action.startsWith('market_data')) {\n await fetch('http://10.0.0.48:3001/api/trading/market-data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(parsed),\n });\n return []; // Halt further nodes (no Telegram/risk)\n }\n} catch (err) {\n // Body isn't JSON, keep processing\n}\nif (/market_data/i.test(body)) {\n // Fallback: drop unknown market_data text payloads\n return [];\n}\n\n// Parse basic signal (existing logic)\nconst symbolMatch = body.match(/\\b(SOL|BTC|ETH)\\b/i);\nconst symbol = symbolMatch ? symbolMatch[1].toUpperCase() + '-PERP' : 'SOL-PERP';\n\nconst direction = body.match(/\\b(sell|short)\\b/i) ? 'short' : 'long';\n\n// Enhanced timeframe extraction supporting multiple formats:\n// - \"buy 5\" \"5\"\n// - \"buy 15\" \"15\"\n// - \"buy 60\" or \"buy 1h\" \"60\"\n// - \"buy 240\" or \"buy 4h\" \"240\"\n// - \"buy D\" or \"buy 1d\" \"D\"\n// - \"buy W\" \"W\"\nconst timeframeMatch = body.match(/\\b(buy|sell)\\s+(\\d+|D|W|M|1h|4h|1d)\\b/i);\nlet timeframe = '5'; // Default to 5min\n\nif (timeframeMatch) {\n const tf = timeframeMatch[2];\n // Convert hour/day notation to minutes\n if (tf === '1h' || tf === '60') {\n timeframe = '60';\n } else if (tf === '4h' || tf === '240') {\n timeframe = '240';\n } else if (tf === '1d' || tf.toUpperCase() === 'D') {\n timeframe = 'D';\n } else if (tf.toUpperCase() === 'W') {\n timeframe = 'W';\n } else if (tf.toUpperCase() === 'M') {\n timeframe = 'M';\n } else {\n timeframe = tf;\n }\n}\n\n// Parse new context metrics from enhanced format:\n// \"SOLT.P buy 15 | ATR:0.65 | ADX:14.3 | RSI:51.3 | VOL:0.87 | POS:59.3 | IND:v8\"\nconst atrMatch = body.match(/ATR:([\\d.]+)/);\nconst atr = atrMatch ? parseFloat(atrMatch[1]) : 0;\n\nconst adxMatch = body.match(/ADX:([\\d.]+)/);\nconst adx = adxMatch ? parseFloat(adxMatch[1]) : 0;\n\nconst rsiMatch = body.match(/RSI:([\\d.]+)/);\nconst rsi = rsiMatch ? parseFloat(rsiMatch[1]) : 0;\n\nconst volumeMatch = body.match(/VOL:([\\d.]+)/);\nconst volumeRatio = volumeMatch ? parseFloat(volumeMatch[1]) : 0;\n\nconst pricePositionMatch = body.match(/POS:([\\d.]+)/);\nconst pricePosition = pricePositionMatch ? parseFloat(pricePositionMatch[1]) : 0;\n\n// Parse indicator version (optional, backward compatible)\nconst indicatorVersionMatch = body.match(/IND:(v\\d+)/i);\nconst indicatorVersion = indicatorVersionMatch ? indicatorVersionMatch[1] : 'v8';\n\nreturn {\n rawMessage: body,\n symbol,\n direction,\n timeframe,\n // Context fields\n atr,\n adx,\n rsi,\n volumeRatio,\n pricePosition,\n // Version tracking (defaults to v8 for backward compatibility)\n indicatorVersion\n};"
},
"id": "97d5b0ad-d078-411f-8f34-c9a81d18d921",
"name": "Parse Signal Enhanced",
@@ -176,7 +176,7 @@
"values": [
{
"name": "message",
"stringValue": "={{ `\ud83d\udfe2 TRADE OPENED\n\n\ud83d\udcca Symbol: ${$('Parse Signal Enhanced').item.json.symbol}\n${$('Parse Signal Enhanced').item.json.direction === 'long' ? '\ud83d\udcc8' : '\ud83d\udcc9'} Direction: ${$('Parse Signal Enhanced').item.json.direction.toUpperCase()}\n\n\ud83d\udcb5 Position: $${$('Execute Trade1').item.json.positionSize}\n\u26a1 Leverage: ${$('Execute Trade1').item.json.leverage}x${$('Execute Trade1').item.json.qualityScore ? `\n\n\u2b50 Quality: ${$('Execute Trade1').item.json.qualityScore}/100` : ''}\n\n\ud83d\udcb0 Entry: $${$('Execute Trade1').item.json.entryPrice.toFixed(4)}\n\ud83c\udfaf TP1: $${$('Execute Trade1').item.json.takeProfit1.toFixed(4)} (${$('Execute Trade1').item.json.tp1Percent}%)\n\ud83c\udfaf TP2: $${$('Execute Trade1').item.json.takeProfit2.toFixed(4)} (${$('Execute Trade1').item.json.tp2Percent}%)\n\ud83d\uded1 SL: $${$('Execute Trade1').item.json.stopLoss.toFixed(4)} (${$('Execute Trade1').item.json.stopLossPercent}%)\n\n\u23f0 ${$now.setZone('Europe/Berlin').toFormat('HH:mm:ss')}\n\u2705 Position monitored` }}"
"stringValue": "={{ const resp = $(\"Execute Trade1\").item.json; const parsed = $(\"Parse Signal Enhanced\").item.json; if (resp.smartEntry && !resp.entryPrice) { return `⏰ SIGNAL QUEUED FOR SMART ENTRY\\n\\n📊 Symbol: ${parsed.symbol}\\n${parsed.direction === \"long\" ? \"📈\" : \"📉\"} Direction: ${parsed.direction.toUpperCase()}\\n\\n🎯 Waiting for optimal entry (pullback)\\n⌛ Entry window: 5 minutes\\n\\n⭐ Quality: ${resp.qualityScore || \"N/A\"}/100\\n\\n⏰ ${$now.setZone(\"Europe/Berlin\").toFormat(\"HH:mm:ss\")}\\n👁 Monitoring price...`; } else if (resp.entryPrice) { return `🟢 TRADE OPENED\\n\\n📊 Symbol: ${parsed.symbol}\\n${parsed.direction === \"long\" ? \"📈\" : \"📉\"} Direction: ${parsed.direction.toUpperCase()}\\n\\n💵 Position: $${resp.positionSize}\\n⚡ Leverage: ${resp.leverage}x${resp.qualityScore ? `\\n\\n⭐ Quality: ${resp.qualityScore}/100` : \"\"}\\n\\n💰 Entry: $${resp.entryPrice.toFixed(4)}\\n🎯 TP1: $${resp.takeProfit1.toFixed(4)} (${resp.tp1Percent}%)\\n🎯 TP2: $${resp.takeProfit2.toFixed(4)} (${resp.tp2Percent}%)\\n🛑 SL: $${resp.stopLoss.toFixed(4)} (${resp.stopLossPercent}%)\\n\\n⏰ ${$now.setZone(\"Europe/Berlin\").toFormat(\"HH:mm:ss\")}\\n✅ Position monitored`; } else { return `📝 SIGNAL PROCESSED\\n\\n📊 Symbol: ${parsed.symbol}\\n${parsed.direction === \"long\" ? \"📈\" : \"📉\"} Direction: ${parsed.direction.toUpperCase()}\\n\\n ${resp.message || \"Response received\"}\\n\\n⏰ ${$now.setZone(\"Europe/Berlin\").toFormat(\"HH:mm:ss\")}`; } }}"
}
]
},
@@ -197,7 +197,7 @@
"values": [
{
"name": "message",
"stringValue": "=\ud83d\udd34 TRADE FAILED\n\n{{ $('Parse Signal Enhanced')').item.json.rawMessage }}\n\n\u274c Error: {{ $json.error || $json.message }}\n\u23f0 {{ $now.setZone('Europe/Berlin').toFormat('HH:mm') }}"
"stringValue": "=🔴 TRADE FAILED\n\n{{ $('Parse Signal Enhanced')').item.json.rawMessage }}\n\n Error: {{ $json.error || $json.message }}\n {{ $now.setZone('Europe/Berlin').toFormat('HH:mm') }}"
}
]
},
@@ -218,7 +218,7 @@
"values": [
{
"name": "message",
"stringValue": "={{ '\u26a0\ufe0f TRADE BLOCKED\\n\\n' + $('Parse Signal Enhanced').item.json.rawMessage + '\\n\\n\ud83d\uded1 Reason: ' + $json.reason + '\\n\ud83d\udccb Details: ' + ($json.details || 'N/A') + '\\n\\n\ud83d\udcca Quality Score: ' + ($json.qualityScore || 'N/A') + '/100' + ($json.qualityReasons && $json.qualityReasons.length > 0 ? '\\n\u26a0\ufe0f Issues:\\n \u2022 ' + $json.qualityReasons.join('\\n \u2022 ') : '') + '\\n\\n\u23f0 ' + $now.setZone('Europe/Berlin').toFormat('HH:mm:ss') }}"
"stringValue": "={{ '⚠️ TRADE BLOCKED\\n\\n' + $('Parse Signal Enhanced').item.json.rawMessage + '\\n\\n🛑 Reason: ' + $json.reason + '\\n📋 Details: ' + ($json.details || 'N/A') + '\\n\\n📊 Quality Score: ' + ($json.qualityScore || 'N/A') + '/100' + ($json.qualityReasons && $json.qualityReasons.length > 0 ? '\\n⚠️ Issues:\\n ' + $json.qualityReasons.join('\\n ') : '') + '\\n\\n ' + $now.setZone('Europe/Berlin').toFormat('HH:mm:ss') }}"
}
]
},
@@ -686,4 +686,4 @@
"instanceId": "e766d4f0b5def8ee8cb8561cd9d2b9ba7733e1907990b6987bca40175f82c379"
},
"tags": []
}
}

View File

@@ -0,0 +1,689 @@
{
"name": "Money Machine",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "tradingview-bot-v4",
"options": {}
},
"id": "c762618c-fac7-4689-9356-8a78fc7160a8",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
-1020,
660
],
"webhookId": "tradingview-bot-v4"
},
{
"parameters": {
"jsCode": "// Get the body - it might be a string or nested in an object\nlet body = $json.body || $json.query?.body || JSON.stringify($json);\n\n// If body is an object, stringify it\nif (typeof body === 'object') {\n body = JSON.stringify(body);\n}\n\n// Forward market data payloads directly to /api/trading/market-data and stop workflow\ntry {\n const parsed = JSON.parse(body);\n const action = parsed?.action?.toLowerCase?.() || '';\n if (action.startsWith('market_data')) {\n await fetch('http://10.0.0.48:3001/api/trading/market-data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(parsed),\n });\n return []; // Halt further nodes (no Telegram/risk)\n }\n} catch (err) {\n // Body isn't JSON, keep processing\n}\nif (/market_data/i.test(body)) {\n // Fallback: drop unknown market_data text payloads\n return [];\n}\n\n// Parse basic signal (existing logic)\nconst symbolMatch = body.match(/\\b(SOL|BTC|ETH)\\b/i);\nconst symbol = symbolMatch ? symbolMatch[1].toUpperCase() + '-PERP' : 'SOL-PERP';\n\nconst direction = body.match(/\\b(sell|short)\\b/i) ? 'short' : 'long';\n\n// Enhanced timeframe extraction supporting multiple formats:\n// - \"buy 5\" \u2192 \"5\"\n// - \"buy 15\" \u2192 \"15\"\n// - \"buy 60\" or \"buy 1h\" \u2192 \"60\"\n// - \"buy 240\" or \"buy 4h\" \u2192 \"240\"\n// - \"buy D\" or \"buy 1d\" \u2192 \"D\"\n// - \"buy W\" \u2192 \"W\"\nconst timeframeMatch = body.match(/\\b(buy|sell)\\s+(\\d+|D|W|M|1h|4h|1d)\\b/i);\nlet timeframe = '5'; // Default to 5min\n\nif (timeframeMatch) {\n const tf = timeframeMatch[2];\n // Convert hour/day notation to minutes\n if (tf === '1h' || tf === '60') {\n timeframe = '60';\n } else if (tf === '4h' || tf === '240') {\n timeframe = '240';\n } else if (tf === '1d' || tf.toUpperCase() === 'D') {\n timeframe = 'D';\n } else if (tf.toUpperCase() === 'W') {\n timeframe = 'W';\n } else if (tf.toUpperCase() === 'M') {\n timeframe = 'M';\n } else {\n timeframe = tf;\n }\n}\n\n// Parse new context metrics from enhanced format:\n// \"SOLT.P buy 15 | ATR:0.65 | ADX:14.3 | RSI:51.3 | VOL:0.87 | POS:59.3 | IND:v8\"\nconst atrMatch = body.match(/ATR:([\\d.]+)/);\nconst atr = atrMatch ? parseFloat(atrMatch[1]) : 0;\n\nconst adxMatch = body.match(/ADX:([\\d.]+)/);\nconst adx = adxMatch ? parseFloat(adxMatch[1]) : 0;\n\nconst rsiMatch = body.match(/RSI:([\\d.]+)/);\nconst rsi = rsiMatch ? parseFloat(rsiMatch[1]) : 0;\n\nconst volumeMatch = body.match(/VOL:([\\d.]+)/);\nconst volumeRatio = volumeMatch ? parseFloat(volumeMatch[1]) : 0;\n\nconst pricePositionMatch = body.match(/POS:([\\d.]+)/);\nconst pricePosition = pricePositionMatch ? parseFloat(pricePositionMatch[1]) : 0;\n\n// Parse indicator version (optional, backward compatible)\nconst indicatorVersionMatch = body.match(/IND:(v\\d+)/i);\nconst indicatorVersion = indicatorVersionMatch ? indicatorVersionMatch[1] : 'v8';\n\nreturn {\n rawMessage: body,\n symbol,\n direction,\n timeframe,\n // Context fields\n atr,\n adx,\n rsi,\n volumeRatio,\n pricePosition,\n // Version tracking (defaults to v8 for backward compatibility)\n indicatorVersion\n};"
},
"id": "97d5b0ad-d078-411f-8f34-c9a81d18d921",
"name": "Parse Signal Enhanced",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-760,
580
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.timeframe }}",
"value2": "15"
}
]
}
},
"id": "2e0bf241-9fb6-40bd-89f6-2dceafe34ef9",
"name": "15min Chart Only?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-760,
260
]
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/check-risk",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $json.symbol }}\",\n \"direction\": \"{{ $json.direction }}\"\n}",
"options": {}
},
"id": "c1165de4-2095-4f5f-b9b1-18e76fd8c47b",
"name": "Check Risk",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-280,
660
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.allowed }}",
"value2": true
}
]
}
},
"id": "b9fa2b47-2acd-4be0-9d50-3f0348e04ec6",
"name": "Risk Passed?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-120,
660
]
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/execute",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $('Parse Signal Enhanced').item.json.symbol }}\",\n \"direction\": \"{{ $('Parse Signal Enhanced').item.json.direction }}\",\n \"timeframe\": \"{{ $('Parse Signal Enhanced').item.json.timeframe }}\",\n \"atr\": {{ $('Parse Signal Enhanced').item.json.atr }},\n \"adx\": {{ $('Parse Signal Enhanced').item.json.adx }},\n \"rsi\": {{ $('Parse Signal Enhanced').item.json.rsi }},\n \"volumeRatio\": {{ $('Parse Signal Enhanced').item.json.volumeRatio }},\n \"pricePosition\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorVersion\": \"{{ $('Parse Signal Enhanced').item.json.indicatorVersion }}\",\n \"signalPrice\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorScore\": {{ $('Parse Signal Enhanced').item.json.indicatorScore || 'null' }}\n}",
"options": {
"timeout": 120000
}
},
"id": "c2ec5f8c-42d1-414f-bdd6-0a440bc8fea9",
"name": "Execute Trade",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
60,
560
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.success }}",
"value2": true
}
]
}
},
"id": "16dbf434-a07c-4666-82f2-cdc8814fe216",
"name": "Trade Success?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
260,
560
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "message",
"stringValue": "={{ `\ud83d\udfe2 TRADE OPENED\n\n\ud83d\udcca Symbol: ${$('Parse Signal Enhanced').item.json.symbol}\n${$('Parse Signal Enhanced').item.json.direction === 'long' ? '\ud83d\udcc8' : '\ud83d\udcc9'} Direction: ${$('Parse Signal Enhanced').item.json.direction.toUpperCase()}\n\n\ud83d\udcb5 Position: $${$('Execute Trade1').item.json.positionSize}\n\u26a1 Leverage: ${$('Execute Trade1').item.json.leverage}x${$('Execute Trade1').item.json.qualityScore ? `\n\n\u2b50 Quality: ${$('Execute Trade1').item.json.qualityScore}/100` : ''}\n\n\ud83d\udcb0 Entry: $${$('Execute Trade1').item.json.entryPrice.toFixed(4)}\n\ud83c\udfaf TP1: $${$('Execute Trade1').item.json.takeProfit1.toFixed(4)} (${$('Execute Trade1').item.json.tp1Percent}%)\n\ud83c\udfaf TP2: $${$('Execute Trade1').item.json.takeProfit2.toFixed(4)} (${$('Execute Trade1').item.json.tp2Percent}%)\n\ud83d\uded1 SL: $${$('Execute Trade1').item.json.stopLoss.toFixed(4)} (${$('Execute Trade1').item.json.stopLossPercent}%)\n\n\u23f0 ${$now.setZone('Europe/Berlin').toFormat('HH:mm:ss')}\n\u2705 Position monitored` }}"
}
]
},
"options": {}
},
"id": "79ab6122-cbd3-4aac-97d7-6b54f64e29b5",
"name": "Format Success",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
460,
460
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "message",
"stringValue": "=\ud83d\udd34 TRADE FAILED\n\n{{ $('Parse Signal Enhanced')').item.json.rawMessage }}\n\n\u274c Error: {{ $json.error || $json.message }}\n\u23f0 {{ $now.setZone('Europe/Berlin').toFormat('HH:mm') }}"
}
]
},
"options": {}
},
"id": "41a0a8be-5004-4e6d-bdc5-9c7edf04eb51",
"name": "Format Error",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
460,
660
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "message",
"stringValue": "={{ '\u26a0\ufe0f TRADE BLOCKED\\n\\n' + $('Parse Signal Enhanced').item.json.rawMessage + '\\n\\n\ud83d\uded1 Reason: ' + $json.reason + '\\n\ud83d\udccb Details: ' + ($json.details || 'N/A') + '\\n\\n\ud83d\udcca Quality Score: ' + ($json.qualityScore || 'N/A') + '/100' + ($json.qualityReasons && $json.qualityReasons.length > 0 ? '\\n\u26a0\ufe0f Issues:\\n \u2022 ' + $json.qualityReasons.join('\\n \u2022 ') : '') + '\\n\\n\u23f0 ' + $now.setZone('Europe/Berlin').toFormat('HH:mm:ss') }}"
}
]
},
"options": {}
},
"id": "da462967-0548-4d57-a6de-cb783c96ac07",
"name": "Format Risk",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
60,
760
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.skipNotification }}",
"value2": true
}
]
}
},
"id": "1a415fb1-5520-4428-9c40-5d105d6b3d30",
"name": "Check Skip Notification",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
160,
760
]
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "254280fd-f547-4302-97a5-30b44d851e12",
"name": "Telegram Success",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
660,
460
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "4ea066c9-4971-408f-b6e2-7d704c13ef55",
"name": "Telegram Error",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
660,
660
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "ee6be7be-1735-4fa3-bd33-6b3fde9414d3",
"name": "Telegram Risk",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
260,
760
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.timeframe }}",
"value2": "5"
}
]
}
},
"id": "8c680565-120d-47dc-83b2-58dcd397168b",
"name": "5min Chart Only?1",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-500,
660
]
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.rawMessage }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "a63da8d2-e255-4933-9fba-a1999d2da31e",
"name": "Trend Signal",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
-260,
860
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"jsCode": "// Get the body - it might be a string or nested in an object\nlet body = $json.body || $json.query?.body || JSON.stringify($json);\n\n// If body is an object, stringify it\nif (typeof body === 'object') {\n body = JSON.stringify(body);\n}\n\n// Parse basic signal (existing logic)\nconst symbolMatch = body.match(/\\b(SOL|BTC|ETH)/i);\nconst symbol = symbolMatch ? symbolMatch[1].toUpperCase() + '-PERP' : 'SOL-PERP';\n\nconst direction = body.match(/\\b(sell|short)\\b/i) ? 'short' : 'long';\n\n// Updated regex to match new format: \"ETH buy 15\" (no .P)\nconst timeframeMatch = body.match(/\\b(buy|sell)\\s+(\\d+|D|W|M)\\b/i);\nconst timeframe = timeframeMatch ? timeframeMatch[2] : '5';\n\n// Parse new context metrics from enhanced format:\n// \"ETH buy 15 | ATR:1.85 | ADX:28.3 | RSI:62.5 | VOL:1.45 | POS:75.3 | IND:v6\"\nconst atrMatch = body.match(/ATR:([\\d.]+)/);\nconst atr = atrMatch ? parseFloat(atrMatch[1]) : 0;\n\nconst adxMatch = body.match(/ADX:([\\d.]+)/);\nconst adx = adxMatch ? parseFloat(adxMatch[1]) : 0;\n\nconst rsiMatch = body.match(/RSI:([\\d.]+)/);\nconst rsi = rsiMatch ? parseFloat(rsiMatch[1]) : 0;\n\nconst volumeMatch = body.match(/VOL:([\\d.]+)/);\nconst volumeRatio = volumeMatch ? parseFloat(volumeMatch[1]) : 0;\n\nconst pricePositionMatch = body.match(/POS:([\\d.]+)/);\nconst pricePosition = pricePositionMatch ? parseFloat(pricePositionMatch[1]) : 0;\n\n// Parse indicator version (optional, backward compatible)\nconst indicatorVersionMatch = body.match(/IND:(v\\d+)/);\nconst indicatorVersion = indicatorVersionMatch ? indicatorVersionMatch[1] : 'v5';\n\nreturn {\n rawMessage: body,\n symbol,\n direction,\n timeframe,\n // Context fields\n atr,\n adx,\n rsi,\n volumeRatio,\n pricePosition,\n // Version tracking (defaults to v5 for backward compatibility)\n indicatorVersion\n};"
},
"id": "81f28bc7-c96a-4021-acac-242e993d9d98",
"name": "Parse Signal Enhanced",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-740,
860
]
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.rawMessage }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "fa3a214c-9f30-4f2d-b727-68ba1877e4c8",
"name": "Trend Signal1",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
-500,
860
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/execute",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $('Parse Signal Enhanced').item.json.symbol }}\",\n \"direction\": \"{{ $('Parse Signal Enhanced').item.json.direction }}\",\n \"timeframe\": \"{{ $('Parse Signal Enhanced').item.json.timeframe }}\",\n \"atr\": {{ $('Parse Signal Enhanced').item.json.atr }},\n \"adx\": {{ $('Parse Signal Enhanced').item.json.adx }},\n \"rsi\": {{ $('Parse Signal Enhanced').item.json.rsi }},\n \"volumeRatio\": {{ $('Parse Signal Enhanced').item.json.volumeRatio }},\n \"pricePosition\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorVersion\": \"{{ $('Parse Signal Enhanced').item.json.indicatorVersion }}\",\n \"signalPrice\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorScore\": {{ $('Parse Signal Enhanced').item.json.indicatorScore || 'null' }}\n}",
"options": {
"timeout": 120000
}
},
"id": "9902ecc4-53b0-402f-8db9-6248e6077740",
"name": "Execute Trade1",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
60,
240
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/check-risk",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $json.symbol }}\",\n \"direction\": \"{{ $json.direction }}\",\n \"timeframe\": \"{{ $json.timeframe }}\",\n \"atr\": {{ $json.atr || 0 }},\n \"adx\": {{ $json.adx || 0 }},\n \"rsi\": {{ $json.rsi || 0 }},\n \"volumeRatio\": {{ $json.volumeRatio || 0 }},\n \"pricePosition\": {{ $json.pricePosition || 0 }}\n}",
"options": {}
},
"id": "55671044-c7c8-4566-b271-9369a1c43158",
"name": "Check Risk1",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-280,
240
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"path": "c034de5f-bcd5-4470-a193-8a16fbfb73eb",
"options": {}
},
"id": "ff525977-6e95-4e45-b742-cedb5f36b4b4",
"name": "Webhook1",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
-1020,
860
],
"webhookId": "c034de5f-bcd5-4470-a193-8a16fbfb73eb"
}
],
"pinData": {},
"connections": {
"Webhook": {
"main": [
[
{
"node": "Parse Signal Enhanced",
"type": "main",
"index": 0
}
]
]
},
"Parse Signal": {
"main": [
[
{
"node": "5min Chart Only?1",
"type": "main",
"index": 0
}
]
]
},
"Check Risk": {
"main": [
[
{
"node": "Risk Passed?",
"type": "main",
"index": 0
}
]
]
},
"Risk Passed?": {
"main": [
[
{
"node": "Execute Trade1",
"type": "main",
"index": 0
}
],
[
{
"node": "Format Risk",
"type": "main",
"index": 0
}
]
]
},
"Execute Trade": {
"main": [
[
{
"node": "Trade Success?",
"type": "main",
"index": 0
}
]
]
},
"Trade Success?": {
"main": [
[
{
"node": "Format Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Format Error",
"type": "main",
"index": 0
}
]
]
},
"Format Success": {
"main": [
[
{
"node": "Telegram Success",
"type": "main",
"index": 0
}
]
]
},
"Format Error": {
"main": [
[
{
"node": "Telegram Error",
"type": "main",
"index": 0
}
]
]
},
"Format Risk": {
"main": [
[
{
"node": "Check Skip Notification",
"type": "main",
"index": 0
}
]
]
},
"5min Chart Only?1": {
"main": [
[
{
"node": "Check Risk1",
"type": "main",
"index": 0
}
],
[
{
"node": "Trend Signal",
"type": "main",
"index": 0
}
]
]
},
"Parse Signal Enhanced": {
"main": [
[
{
"node": "Execute Trade",
"type": "main",
"index": 0
}
]
]
},
"Execute Trade1": {
"main": [
[
{
"node": "Trade Success?",
"type": "main",
"index": 0
}
]
]
},
"Check Risk1": {
"main": [
[
{
"node": "Risk Passed?",
"type": "main",
"index": 0
}
]
]
},
"Check Skip Notification": {
"main": [
[],
[
{
"node": "Telegram Risk",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "955bd768-0c3b-490a-9c6b-5c01bc2f6d44",
"id": "gUDqTiHyHSfRUXv6",
"meta": {
"instanceId": "e766d4f0b5def8ee8cb8561cd9d2b9ba7733e1907990b6987bca40175f82c379"
},
"tags": []
}

View File

@@ -0,0 +1,689 @@
{
"name": "Money Machine",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "tradingview-bot-v4",
"options": {}
},
"id": "c762618c-fac7-4689-9356-8a78fc7160a8",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
-1020,
660
],
"webhookId": "tradingview-bot-v4"
},
{
"parameters": {
"jsCode": "// Get the body - it might be a string or nested in an object\nlet body = $json.body || $json.query?.body || JSON.stringify($json);\n\n// If body is an object, stringify it\nif (typeof body === 'object') {\n body = JSON.stringify(body);\n}\n\n// Forward market data payloads directly to /api/trading/market-data and stop workflow\ntry {\n const parsed = JSON.parse(body);\n const action = parsed?.action?.toLowerCase?.() || '';\n if (action.startsWith('market_data')) {\n await fetch('http://10.0.0.48:3001/api/trading/market-data', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(parsed),\n });\n return []; // Halt further nodes (no Telegram/risk)\n }\n} catch (err) {\n // Body isn't JSON, keep processing\n}\nif (/market_data/i.test(body)) {\n // Fallback: drop unknown market_data text payloads\n return [];\n}\n\n// Parse basic signal (existing logic)\nconst symbolMatch = body.match(/\\b(SOL|BTC|ETH)\\b/i);\nconst symbol = symbolMatch ? symbolMatch[1].toUpperCase() + '-PERP' : 'SOL-PERP';\n\nconst direction = body.match(/\\b(sell|short)\\b/i) ? 'short' : 'long';\n\n// Enhanced timeframe extraction supporting multiple formats:\n// - \"buy 5\" \u2192 \"5\"\n// - \"buy 15\" \u2192 \"15\"\n// - \"buy 60\" or \"buy 1h\" \u2192 \"60\"\n// - \"buy 240\" or \"buy 4h\" \u2192 \"240\"\n// - \"buy D\" or \"buy 1d\" \u2192 \"D\"\n// - \"buy W\" \u2192 \"W\"\nconst timeframeMatch = body.match(/\\b(buy|sell)\\s+(\\d+|D|W|M|1h|4h|1d)\\b/i);\nlet timeframe = '5'; // Default to 5min\n\nif (timeframeMatch) {\n const tf = timeframeMatch[2];\n // Convert hour/day notation to minutes\n if (tf === '1h' || tf === '60') {\n timeframe = '60';\n } else if (tf === '4h' || tf === '240') {\n timeframe = '240';\n } else if (tf === '1d' || tf.toUpperCase() === 'D') {\n timeframe = 'D';\n } else if (tf.toUpperCase() === 'W') {\n timeframe = 'W';\n } else if (tf.toUpperCase() === 'M') {\n timeframe = 'M';\n } else {\n timeframe = tf;\n }\n}\n\n// Parse new context metrics from enhanced format:\n// \"SOLT.P buy 15 | ATR:0.65 | ADX:14.3 | RSI:51.3 | VOL:0.87 | POS:59.3 | IND:v8\"\nconst atrMatch = body.match(/ATR:([\\d.]+)/);\nconst atr = atrMatch ? parseFloat(atrMatch[1]) : 0;\n\nconst adxMatch = body.match(/ADX:([\\d.]+)/);\nconst adx = adxMatch ? parseFloat(adxMatch[1]) : 0;\n\nconst rsiMatch = body.match(/RSI:([\\d.]+)/);\nconst rsi = rsiMatch ? parseFloat(rsiMatch[1]) : 0;\n\nconst volumeMatch = body.match(/VOL:([\\d.]+)/);\nconst volumeRatio = volumeMatch ? parseFloat(volumeMatch[1]) : 0;\n\nconst pricePositionMatch = body.match(/POS:([\\d.]+)/);\nconst pricePosition = pricePositionMatch ? parseFloat(pricePositionMatch[1]) : 0;\n\n// Parse indicator version (optional, backward compatible)\nconst indicatorVersionMatch = body.match(/IND:(v\\d+)/i);\nconst indicatorVersion = indicatorVersionMatch ? indicatorVersionMatch[1] : 'v8';\n\nreturn {\n rawMessage: body,\n symbol,\n direction,\n timeframe,\n // Context fields\n atr,\n adx,\n rsi,\n volumeRatio,\n pricePosition,\n // Version tracking (defaults to v8 for backward compatibility)\n indicatorVersion\n};"
},
"id": "97d5b0ad-d078-411f-8f34-c9a81d18d921",
"name": "Parse Signal Enhanced",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-760,
580
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.timeframe }}",
"value2": "15"
}
]
}
},
"id": "2e0bf241-9fb6-40bd-89f6-2dceafe34ef9",
"name": "15min Chart Only?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-760,
260
]
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/check-risk",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $json.symbol }}\",\n \"direction\": \"{{ $json.direction }}\"\n}",
"options": {}
},
"id": "c1165de4-2095-4f5f-b9b1-18e76fd8c47b",
"name": "Check Risk",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-280,
660
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.allowed }}",
"value2": true
}
]
}
},
"id": "b9fa2b47-2acd-4be0-9d50-3f0348e04ec6",
"name": "Risk Passed?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-120,
660
]
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/execute",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $('Parse Signal Enhanced').item.json.symbol }}\",\n \"direction\": \"{{ $('Parse Signal Enhanced').item.json.direction }}\",\n \"timeframe\": \"{{ $('Parse Signal Enhanced').item.json.timeframe }}\",\n \"atr\": {{ $('Parse Signal Enhanced').item.json.atr }},\n \"adx\": {{ $('Parse Signal Enhanced').item.json.adx }},\n \"rsi\": {{ $('Parse Signal Enhanced').item.json.rsi }},\n \"volumeRatio\": {{ $('Parse Signal Enhanced').item.json.volumeRatio }},\n \"pricePosition\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorVersion\": \"{{ $('Parse Signal Enhanced').item.json.indicatorVersion }}\",\n \"signalPrice\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorScore\": {{ $('Parse Signal Enhanced').item.json.indicatorScore || 'null' }}\n}",
"options": {
"timeout": 120000
}
},
"id": "c2ec5f8c-42d1-414f-bdd6-0a440bc8fea9",
"name": "Execute Trade",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
60,
560
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.success }}",
"value2": true
}
]
}
},
"id": "16dbf434-a07c-4666-82f2-cdc8814fe216",
"name": "Trade Success?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
260,
560
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "message",
"stringValue": "={{ `\ud83d\udfe2 TRADE OPENED\n\n\ud83d\udcca Symbol: ${$('Parse Signal Enhanced').item.json.symbol}\n${$('Parse Signal Enhanced').item.json.direction === 'long' ? '\ud83d\udcc8' : '\ud83d\udcc9'} Direction: ${$('Parse Signal Enhanced').item.json.direction.toUpperCase()}\n\n\ud83d\udcb5 Position: $${$('Execute Trade1').item.json.positionSize}\n\u26a1 Leverage: ${$('Execute Trade1').item.json.leverage}x${$('Execute Trade1').item.json.qualityScore ? `\n\n\u2b50 Quality: ${$('Execute Trade1').item.json.qualityScore}/100` : ''}\n\n\ud83d\udcb0 Entry: $${$('Execute Trade1').item.json.entryPrice.toFixed(4)}\n\ud83c\udfaf TP1: $${$('Execute Trade1').item.json.takeProfit1.toFixed(4)} (${$('Execute Trade1').item.json.tp1Percent}%)\n\ud83c\udfaf TP2: $${$('Execute Trade1').item.json.takeProfit2.toFixed(4)} (${$('Execute Trade1').item.json.tp2Percent}%)\n\ud83d\uded1 SL: $${$('Execute Trade1').item.json.stopLoss.toFixed(4)} (${$('Execute Trade1').item.json.stopLossPercent}%)\n\n\u23f0 ${$now.setZone('Europe/Berlin').toFormat('HH:mm:ss')}\n\u2705 Position monitored` }}"
}
]
},
"options": {}
},
"id": "79ab6122-cbd3-4aac-97d7-6b54f64e29b5",
"name": "Format Success",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
460,
460
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "message",
"stringValue": "=\ud83d\udd34 TRADE FAILED\n\n{{ $('Parse Signal Enhanced')').item.json.rawMessage }}\n\n\u274c Error: {{ $json.error || $json.message }}\n\u23f0 {{ $now.setZone('Europe/Berlin').toFormat('HH:mm') }}"
}
]
},
"options": {}
},
"id": "41a0a8be-5004-4e6d-bdc5-9c7edf04eb51",
"name": "Format Error",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
460,
660
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "message",
"stringValue": "={{ '\u26a0\ufe0f TRADE BLOCKED\\n\\n' + $('Parse Signal Enhanced').item.json.rawMessage + '\\n\\n\ud83d\uded1 Reason: ' + $json.reason + '\\n\ud83d\udccb Details: ' + ($json.details || 'N/A') + '\\n\\n\ud83d\udcca Quality Score: ' + ($json.qualityScore || 'N/A') + '/100' + ($json.qualityReasons && $json.qualityReasons.length > 0 ? '\\n\u26a0\ufe0f Issues:\\n \u2022 ' + $json.qualityReasons.join('\\n \u2022 ') : '') + '\\n\\n\u23f0 ' + $now.setZone('Europe/Berlin').toFormat('HH:mm:ss') }}"
}
]
},
"options": {}
},
"id": "da462967-0548-4d57-a6de-cb783c96ac07",
"name": "Format Risk",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
60,
760
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $json.skipNotification }}",
"value2": true
}
]
}
},
"id": "1a415fb1-5520-4428-9c40-5d105d6b3d30",
"name": "Check Skip Notification",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
160,
760
]
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "254280fd-f547-4302-97a5-30b44d851e12",
"name": "Telegram Success",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
660,
460
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "4ea066c9-4971-408f-b6e2-7d704c13ef55",
"name": "Telegram Error",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
660,
660
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.message }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "ee6be7be-1735-4fa3-bd33-6b3fde9414d3",
"name": "Telegram Risk",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
260,
760
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.timeframe }}",
"value2": "5"
}
]
}
},
"id": "8c680565-120d-47dc-83b2-58dcd397168b",
"name": "5min Chart Only?1",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
-500,
660
]
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.rawMessage }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "a63da8d2-e255-4933-9fba-a1999d2da31e",
"name": "Trend Signal",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
-260,
860
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"jsCode": "// Get the body - it might be a string or nested in an object\nlet body = $json.body || $json.query?.body || JSON.stringify($json);\n\n// If body is an object, stringify it\nif (typeof body === 'object') {\n body = JSON.stringify(body);\n}\n\n// Parse basic signal (existing logic)\nconst symbolMatch = body.match(/\\b(SOL|BTC|ETH)/i);\nconst symbol = symbolMatch ? symbolMatch[1].toUpperCase() + '-PERP' : 'SOL-PERP';\n\nconst direction = body.match(/\\b(sell|short)\\b/i) ? 'short' : 'long';\n\n// Updated regex to match new format: \"ETH buy 15\" (no .P)\nconst timeframeMatch = body.match(/\\b(buy|sell)\\s+(\\d+|D|W|M)\\b/i);\nconst timeframe = timeframeMatch ? timeframeMatch[2] : '5';\n\n// Parse new context metrics from enhanced format:\n// \"ETH buy 15 | ATR:1.85 | ADX:28.3 | RSI:62.5 | VOL:1.45 | POS:75.3 | IND:v6\"\nconst atrMatch = body.match(/ATR:([\\d.]+)/);\nconst atr = atrMatch ? parseFloat(atrMatch[1]) : 0;\n\nconst adxMatch = body.match(/ADX:([\\d.]+)/);\nconst adx = adxMatch ? parseFloat(adxMatch[1]) : 0;\n\nconst rsiMatch = body.match(/RSI:([\\d.]+)/);\nconst rsi = rsiMatch ? parseFloat(rsiMatch[1]) : 0;\n\nconst volumeMatch = body.match(/VOL:([\\d.]+)/);\nconst volumeRatio = volumeMatch ? parseFloat(volumeMatch[1]) : 0;\n\nconst pricePositionMatch = body.match(/POS:([\\d.]+)/);\nconst pricePosition = pricePositionMatch ? parseFloat(pricePositionMatch[1]) : 0;\n\n// Parse indicator version (optional, backward compatible)\nconst indicatorVersionMatch = body.match(/IND:(v\\d+)/);\nconst indicatorVersion = indicatorVersionMatch ? indicatorVersionMatch[1] : 'v5';\n\nreturn {\n rawMessage: body,\n symbol,\n direction,\n timeframe,\n // Context fields\n atr,\n adx,\n rsi,\n volumeRatio,\n pricePosition,\n // Version tracking (defaults to v5 for backward compatibility)\n indicatorVersion\n};"
},
"id": "81f28bc7-c96a-4021-acac-242e993d9d98",
"name": "Parse Signal Enhanced",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-740,
860
]
},
{
"parameters": {
"chatId": "579304651",
"text": "={{ $json.rawMessage }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "fa3a214c-9f30-4f2d-b727-68ba1877e4c8",
"name": "Trend Signal1",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
-500,
860
],
"credentials": {
"telegramApi": {
"id": "Csk5cg4HtaSqP5jJ",
"name": "Telegram account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/execute",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $('Parse Signal Enhanced').item.json.symbol }}\",\n \"direction\": \"{{ $('Parse Signal Enhanced').item.json.direction }}\",\n \"timeframe\": \"{{ $('Parse Signal Enhanced').item.json.timeframe }}\",\n \"atr\": {{ $('Parse Signal Enhanced').item.json.atr }},\n \"adx\": {{ $('Parse Signal Enhanced').item.json.adx }},\n \"rsi\": {{ $('Parse Signal Enhanced').item.json.rsi }},\n \"volumeRatio\": {{ $('Parse Signal Enhanced').item.json.volumeRatio }},\n \"pricePosition\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorVersion\": \"{{ $('Parse Signal Enhanced').item.json.indicatorVersion }}\",\n \"signalPrice\": {{ $('Parse Signal Enhanced').item.json.pricePosition }},\n \"indicatorScore\": {{ $('Parse Signal Enhanced').item.json.indicatorScore || 'null' }}\n}",
"options": {
"timeout": 120000
}
},
"id": "9902ecc4-53b0-402f-8db9-6248e6077740",
"name": "Execute Trade1",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
60,
240
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"method": "POST",
"url": "http://10.0.0.48:3001/api/trading/check-risk",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer 2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"symbol\": \"{{ $json.symbol }}\",\n \"direction\": \"{{ $json.direction }}\",\n \"timeframe\": \"{{ $json.timeframe }}\",\n \"atr\": {{ $json.atr || 0 }},\n \"adx\": {{ $json.adx || 0 }},\n \"rsi\": {{ $json.rsi || 0 }},\n \"volumeRatio\": {{ $json.volumeRatio || 0 }},\n \"pricePosition\": {{ $json.pricePosition || 0 }}\n}",
"options": {}
},
"id": "55671044-c7c8-4566-b271-9369a1c43158",
"name": "Check Risk1",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-280,
240
],
"credentials": {
"httpHeaderAuth": {
"id": "MATuNdkZclq5ISbr",
"name": "Header Auth account"
}
}
},
{
"parameters": {
"path": "c034de5f-bcd5-4470-a193-8a16fbfb73eb",
"options": {}
},
"id": "ff525977-6e95-4e45-b742-cedb5f36b4b4",
"name": "Webhook1",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
-1020,
860
],
"webhookId": "c034de5f-bcd5-4470-a193-8a16fbfb73eb"
}
],
"pinData": {},
"connections": {
"Webhook": {
"main": [
[
{
"node": "Parse Signal Enhanced",
"type": "main",
"index": 0
}
]
]
},
"Parse Signal": {
"main": [
[
{
"node": "5min Chart Only?1",
"type": "main",
"index": 0
}
]
]
},
"Check Risk": {
"main": [
[
{
"node": "Risk Passed?",
"type": "main",
"index": 0
}
]
]
},
"Risk Passed?": {
"main": [
[
{
"node": "Execute Trade1",
"type": "main",
"index": 0
}
],
[
{
"node": "Format Risk",
"type": "main",
"index": 0
}
]
]
},
"Execute Trade": {
"main": [
[
{
"node": "Trade Success?",
"type": "main",
"index": 0
}
]
]
},
"Trade Success?": {
"main": [
[
{
"node": "Format Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Format Error",
"type": "main",
"index": 0
}
]
]
},
"Format Success": {
"main": [
[
{
"node": "Telegram Success",
"type": "main",
"index": 0
}
]
]
},
"Format Error": {
"main": [
[
{
"node": "Telegram Error",
"type": "main",
"index": 0
}
]
]
},
"Format Risk": {
"main": [
[
{
"node": "Check Skip Notification",
"type": "main",
"index": 0
}
]
]
},
"5min Chart Only?1": {
"main": [
[
{
"node": "Check Risk1",
"type": "main",
"index": 0
}
],
[
{
"node": "Trend Signal",
"type": "main",
"index": 0
}
]
]
},
"Parse Signal Enhanced": {
"main": [
[
{
"node": "Execute Trade",
"type": "main",
"index": 0
}
]
]
},
"Execute Trade1": {
"main": [
[
{
"node": "Trade Success?",
"type": "main",
"index": 0
}
]
]
},
"Check Risk1": {
"main": [
[
{
"node": "Risk Passed?",
"type": "main",
"index": 0
}
]
]
},
"Check Skip Notification": {
"main": [
[],
[
{
"node": "Telegram Risk",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "955bd768-0c3b-490a-9c6b-5c01bc2f6d44",
"id": "gUDqTiHyHSfRUXv6",
"meta": {
"instanceId": "e766d4f0b5def8ee8cb8561cd9d2b9ba7733e1907990b6987bca40175f82c379"
},
"tags": []
}