From 184b8f8a5b7522f93efe3f0216b0cbccc23f571d Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Thu, 1 Jan 2026 15:47:33 +0100 Subject: [PATCH] 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 --- .github/copilot-instructions.md | 2 +- app/api/trading/execute/route.ts | 11 +- docs/N8N_WORKFLOW_DOCUMENTATION.md | 390 ++++++++++ workflows/trading/Money_Machine.json | 10 +- ..._Machine.json.backup-before-smartentry-fix | 689 ++++++++++++++++++ .../Money_Machine.json.backup-smartentry-fix | 689 ++++++++++++++++++ 6 files changed, 1784 insertions(+), 7 deletions(-) create mode 100644 docs/N8N_WORKFLOW_DOCUMENTATION.md create mode 100644 workflows/trading/Money_Machine.json.backup-before-smartentry-fix create mode 100644 workflows/trading/Money_Machine.json.backup-smartentry-fix diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d8e8701..8790351 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -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" ] } } diff --git a/app/api/trading/execute/route.ts b/app/api/trading/execute/route.ts index b7e63be..7293e7c 100644 --- a/app/api/trading/execute/route.ts +++ b/app/api/trading/execute/route.ts @@ -539,8 +539,17 @@ export async function POST(request: NextRequest): Promise= 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 diff --git a/docs/N8N_WORKFLOW_DOCUMENTATION.md b/docs/N8N_WORKFLOW_DOCUMENTATION.md new file mode 100644 index 0000000..345d342 --- /dev/null +++ b/docs/N8N_WORKFLOW_DOCUMENTATION.md @@ -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: " + +# Get specific workflow +curl -s -X GET "https://flow.egonetix.de/api/v1/workflows/gUDqTiHyHSfRUXv6" \ + -H "X-N8N-API-KEY: " + +# Get workflow executions +curl -s -X GET "https://flow.egonetix.de/api/v1/executions?workflowId=gUDqTiHyHSfRUXv6" \ + -H "X-N8N-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: " | jq '.[].status' + +# Check workflow is active +curl -s -X GET "https://flow.egonetix.de/api/v1/workflows/gUDqTiHyHSfRUXv6" \ + -H "X-N8N-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: " \ + -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 | - | + diff --git a/workflows/trading/Money_Machine.json b/workflows/trading/Money_Machine.json index 5b926ee..0e98235 100644 --- a/workflows/trading/Money_Machine.json +++ b/workflows/trading/Money_Machine.json @@ -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": [] -} \ No newline at end of file +} diff --git a/workflows/trading/Money_Machine.json.backup-before-smartentry-fix b/workflows/trading/Money_Machine.json.backup-before-smartentry-fix new file mode 100644 index 0000000..5b926ee --- /dev/null +++ b/workflows/trading/Money_Machine.json.backup-before-smartentry-fix @@ -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": [] +} \ No newline at end of file diff --git a/workflows/trading/Money_Machine.json.backup-smartentry-fix b/workflows/trading/Money_Machine.json.backup-smartentry-fix new file mode 100644 index 0000000..5b926ee --- /dev/null +++ b/workflows/trading/Money_Machine.json.backup-smartentry-fix @@ -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": [] +} \ No newline at end of file