{
  "name": "Master Agent - Orchestrator",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 2
            }
          ]
        }
      },
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Trading Hours - Chicago Time (CT)\n// Futures Session: 5:00 PM CT to 3:55 PM CT (next day)\n// Flatten: 3:55 PM CT (close all positions - prop firm rule)\n// Maintenance: 4:00 PM - 5:00 PM CT daily\n// Weekend: Sat all day + Sun before 5 PM CT\n\nconst now = new Date();\nconst ct = new Intl.DateTimeFormat('en-US', {\n  timeZone: 'America/Chicago',\n  hour: 'numeric', minute: 'numeric', hour12: false,\n  weekday: 'short'\n}).formatToParts(now);\n\nconst ctH = parseInt(ct.find(p => p.type === 'hour').value);\nconst ctM = parseInt(ct.find(p => p.type === 'minute').value);\nconst ctDay = ct.find(p => p.type === 'weekday').value;\n\n// Weekend: Saturday closed\nif (ctDay === 'Sat') return [];\n// Sunday before 5 PM closed\nif (ctDay === 'Sun' && ctH < 17) return [];\n// Friday after 4 PM = weekend\nif (ctDay === 'Fri' && ctH >= 16) return [];\n\n// Daily maintenance: 4:00 PM - 5:00 PM CT\nif (ctH === 16) return [];\n\n// Bot active check\nconst sd = $getWorkflowStaticData('global');\nif (sd.botActive === false) return [];\n\n// Flatten period: 3:55 PM - 4:00 PM CT\n// CLOSE ALL POSITIONS - prop firm cancels account if holding past session\nconst shouldFlatten = (ctH === 15 && ctM >= 55);\n// No new positions after 3:50 PM CT (5 min buffer)\nconst noNewPositions = (ctH === 15 && ctM >= 50);\n\nreturn [{json: {\n  timestamp: now.toISOString(),\n  ctHour: ctH,\n  ctMinute: ctM,\n  ctDay: ctDay,\n  shouldFlatten: shouldFlatten,\n  noNewPositions: noNewPositions,\n  session: ctH >= 17 ? 'evening' : ctH < 9 ? 'overnight' : 'day'\n}}];"
      },
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "name": "Check Trading Hours",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Token cache logic - reuses token for 85 minutes\nconst staticData = $getWorkflowStaticData('global');\nconst now = Date.now();\n\n// Check if we have a valid cached token\nif (staticData.accessToken && staticData.tokenExpiry && now < staticData.tokenExpiry) {\n  return [{\n    json: {\n      accessToken: staticData.accessToken,\n      mdAccessToken: staticData.mdAccessToken || staticData.accessToken,\n      cached: true\n    }\n  }];\n}\n\n// Need new token - return flag\nreturn [{ json: { needsAuth: true } }];"
      },
      "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "name": "Auth Manager",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-needs-auth",
              "leftValue": "={{ $json.needsAuth }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
      "name": "IF Needs Auth",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        660,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://demo.tradovateapi.com/v1/auth/accesstokenrequest",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ name: $env.TRADOVATE_USER || 'USER', password: $env.TRADOVATE_PASS || 'PASS', appId: 'DayTraderBot', appVersion: '1.0', deviceId: 'n8n-lucid-bot' }) }}"
      },
      "id": "e5f6a7b8-c9d0-1234-efab-345678901234",
      "name": "HTTP Auth Tradovate",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        -100
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst authResponse = $input.first().json;\n\nstaticData.accessToken = authResponse.accessToken;\nstaticData.mdAccessToken = authResponse.mdAccessToken || authResponse.accessToken;\nstaticData.tokenExpiry = Date.now() + 85 * 60 * 1000; // 85 minutes\n\nreturn [{\n  json: {\n    accessToken: authResponse.accessToken,\n    mdAccessToken: staticData.mdAccessToken,\n    cached: false\n  }\n}];"
      },
      "id": "f6a7b8c9-d0e1-2345-fabc-456789012345",
      "name": "Cache Token",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1100,
        -100
      ]
    },
    {
      "parameters": {
        "mode": "chooseBranch",
        "output": "empty"
      },
      "id": "a7b8c9d0-e1f2-3456-abcd-567890123456",
      "name": "Merge Auth",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1320,
        0
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://demo.tradovateapi.com/v1/account/list",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.accessToken }}"
            }
          ]
        }
      },
      "id": "b8c9d0e1-f2a3-4567-bcde-678901234567",
      "name": "HTTP Get Account",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1540,
        -200
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://demo.tradovateapi.com/v1/position/list",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Merge Auth').first().json.accessToken }}"
            }
          ]
        }
      },
      "id": "c9d0e1f2-a3b4-5678-cdef-789012345678",
      "name": "HTTP Get Positions",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1540,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Get trading configuration from workflow static data\nconst staticData = $getWorkflowStaticData('global');\n\nconst config = {\n  botActive: staticData.botActive !== false, // default true\n  maxQtyMNQ: staticData.maxQtyMNQ || 1,\n  maxQtyMGC: staticData.maxQtyMGC || 1,\n  maxDrawdownMNQ: staticData.maxDrawdownMNQ || 500,\n  maxDrawdownMGC: staticData.maxDrawdownMGC || 300,\n  activeStrategies: staticData.activeStrategies || ['all'],\n  activeAgents: staticData.activeAgents || ['ICT', 'VOLUME', 'TECHNICAL', 'NEWS', 'FIBONACCI', 'CORRELATION', 'SESSION'],\n  dailyPnL: staticData.dailyPnL || 0,\n  tradesThisDay: staticData.tradesThisDay || 0\n};\n\nif (!config.botActive) {\n  return []; // stops execution if bot is paused\n}\n\nreturn [{ json: config }];"
      },
      "id": "d0e1f2a3-b4c5-6789-defa-890123456789",
      "name": "Get Config",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1540,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// Prepare market data context for sub-workflows\nconst accessToken = $('Merge Auth').first().json.accessToken;\nconst config = $('Get Config').first().json;\n\nreturn [{\n  json: {\n    symbol_mnq: 'MNQM5',\n    symbol_mgc: 'MGCM5',\n    accessToken: accessToken,\n    config: config\n  }\n}];"
      },
      "id": "e1f2a3b4-c5d6-7890-efab-901234567890",
      "name": "Get Market Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        0
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.twelvedata.com/time_series?symbol=NQ&interval=1min&outputsize=100&apikey={{ $env.TWELVE_DATA_KEY || '72309ee97bfe49f29f0f7a92d5337601' }}",
        "options": {}
      },
      "id": "f2a3b4c5-d6e7-8901-fabc-012345678901",
      "name": "HTTP MNQ 1m",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1980,
        -100
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.twelvedata.com/time_series?symbol=NQ&interval=5min&outputsize=100&apikey={{ $env.TWELVE_DATA_KEY || '72309ee97bfe49f29f0f7a92d5337601' }}",
        "options": {}
      },
      "id": "a3b4c5d6-e7f8-9012-abcd-123456789abc",
      "name": "HTTP MNQ 5m",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1980,
        100
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.twelvedata.com/time_series?symbol=GC&interval=1min&outputsize=100&apikey={{ $env.TWELVE_DATA_KEY || '72309ee97bfe49f29f0f7a92d5337601' }}",
        "options": {}
      },
      "id": "mgc-1m-node-id-0001",
      "name": "HTTP MGC 1m",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1980,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.twelvedata.com/time_series?symbol=GC&interval=5min&outputsize=100&apikey={{ $env.TWELVE_DATA_KEY || '72309ee97bfe49f29f0f7a92d5337601' }}",
        "options": {}
      },
      "id": "mgc-5m-node-id-0002",
      "name": "HTTP MGC 5m",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1980,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "const candles1mRaw = $('HTTP MNQ 1m').first().json;\nconst candles5mRaw = $('HTTP MNQ 5m').first().json;\n\n// MGC data\nlet mgcCandles1mRaw, mgcCandles5mRaw;\ntry { mgcCandles1mRaw = $('HTTP MGC 1m').first().json; } catch(e) { mgcCandles1mRaw = { values: [] }; }\ntry { mgcCandles5mRaw = $('HTTP MGC 5m').first().json; } catch(e) { mgcCandles5mRaw = { values: [] }; }\n\n// Flatten/noNewPositions flags from Check Trading Hours\nconst tradingHoursData = $('Check Trading Hours').first().json;\nconst shouldFlatten = tradingHoursData.shouldFlatten || false;\nconst noNewPositions = tradingHoursData.noNewPositions || false;\n\nconst config = $('Get Config').first().json;\n\n// Parse candles from Twelve Data format\nfunction parseCandles(data) {\n  const values = data?.values || data?.body?.values || [];\n  return values.reverse().map(v => ({\n    time: v.datetime,\n    open: parseFloat(v.open),\n    high: parseFloat(v.high),\n    low: parseFloat(v.low),\n    close: parseFloat(v.close),\n    volume: parseInt(v.volume || 0)\n  }));\n}\n\nconst candles_1m = parseCandles(candles1mRaw);\nconst candles_5m = parseCandles(candles5mRaw);\n\nif (candles_1m.length === 0) {\n  return [{ json: { error: 'No candle data available', indicators: {}, candles_1m: [], candles_5m: [] } }];\n}\n\n// === INDICATOR CALCULATIONS ===\n\n// EMA calculation\nfunction calcEMA(data, period) {\n  if (data.length < period) return { value: 0, series: [] };\n  const k = 2 / (period + 1);\n  let ema = data.slice(0, period).reduce((s, v) => s + v, 0) / period;\n  const series = [ema];\n  for (let i = period; i < data.length; i++) {\n    ema = data[i] * k + ema * (1 - k);\n    series.push(ema);\n  }\n  return { value: ema, series };\n}\n\n// RSI\nfunction calcRSI(closes, period) {\n  if (closes.length < period + 1) return 50;\n  let gains = 0, losses = 0;\n  for (let i = 1; i <= period; i++) {\n    const diff = closes[i] - closes[i-1];\n    if (diff > 0) gains += diff; else losses -= diff;\n  }\n  let avgGain = gains / period;\n  let avgLoss = losses / period;\n  for (let i = period + 1; i < closes.length; i++) {\n    const diff = closes[i] - closes[i-1];\n    avgGain = (avgGain * (period - 1) + (diff > 0 ? diff : 0)) / period;\n    avgLoss = (avgLoss * (period - 1) + (diff < 0 ? -diff : 0)) / period;\n  }\n  if (avgLoss === 0) return 100;\n  const rs = avgGain / avgLoss;\n  return 100 - 100 / (1 + rs);\n}\n\n// ATR\nfunction calcATR(candles, period) {\n  if (candles.length < period + 1) return 0;\n  const trs = [];\n  for (let i = 1; i < candles.length; i++) {\n    const tr = Math.max(\n      candles[i].high - candles[i].low,\n      Math.abs(candles[i].high - candles[i-1].close),\n      Math.abs(candles[i].low - candles[i-1].close)\n    );\n    trs.push(tr);\n  }\n  let atr = trs.slice(0, period).reduce((s, v) => s + v, 0) / period;\n  for (let i = period; i < trs.length; i++) {\n    atr = (atr * (period - 1) + trs[i]) / period;\n  }\n  return atr;\n}\n\n// Bollinger Bands\nfunction calcBB(closes, period, stdDev) {\n  if (closes.length < period) return { upper: 0, middle: 0, lower: 0, width: 0 };\n  const slice = closes.slice(-period);\n  const mean = slice.reduce((s, v) => s + v, 0) / period;\n  const variance = slice.reduce((s, v) => s + (v - mean) ** 2, 0) / period;\n  const std = Math.sqrt(variance);\n  return {\n    upper: mean + stdDev * std,\n    middle: mean,\n    lower: mean - stdDev * std,\n    width: (2 * stdDev * std) / mean\n  };\n}\n\n// VWAP\nfunction calcVWAP(candles) {\n  if (candles.length === 0) return { value: 0, upper1SD: 0, lower1SD: 0, upper2SD: 0, lower2SD: 0 };\n  let cumVol = 0, cumTP = 0, cumTP2 = 0;\n  for (const c of candles) {\n    const tp = (c.high + c.low + c.close) / 3;\n    const vol = c.volume || 1;\n    cumVol += vol;\n    cumTP += tp * vol;\n    cumTP2 += tp * tp * vol;\n  }\n  const vwap = cumTP / cumVol;\n  const variance = cumTP2 / cumVol - vwap * vwap;\n  const std = Math.sqrt(Math.max(0, variance));\n  return { value: vwap, upper1SD: vwap + std, lower1SD: vwap - std, upper2SD: vwap + 2*std, lower2SD: vwap - 2*std };\n}\n\n// Volume Delta\nfunction calcVolumeDelta(candles) {\n  let cumDelta = 0;\n  return candles.map(c => {\n    const delta = c.close >= c.open ? c.volume : -c.volume;\n    cumDelta += delta;\n    return {\n      time: c.time,\n      buyVol: c.close >= c.open ? c.volume : 0,\n      sellVol: c.close < c.open ? c.volume : 0,\n      delta,\n      cumDelta\n    };\n  });\n}\n\n// Swing Highs/Lows\nfunction findSwings(candles, lookback) {\n  const highs = [], lows = [];\n  for (let i = lookback; i < candles.length - lookback; i++) {\n    let isHigh = true, isLow = true;\n    for (let j = 1; j <= lookback; j++) {\n      if (candles[i].high <= candles[i-j].high || candles[i].high <= candles[i+j].high) isHigh = false;\n      if (candles[i].low >= candles[i-j].low || candles[i].low >= candles[i+j].low) isLow = false;\n    }\n    if (isHigh) highs.push({ price: candles[i].high, index: i, time: candles[i].time });\n    if (isLow) lows.push({ price: candles[i].low, index: i, time: candles[i].time });\n  }\n  return { swingHighs: highs, swingLows: lows };\n}\n\n// Fair Value Gaps\nfunction findFVGs(candles, tf) {\n  const fvgs = [];\n  for (let i = 2; i < candles.length; i++) {\n    if (candles[i].low > candles[i-2].high) {\n      fvgs.push({\n        type: 'BULLISH',\n        high: candles[i].low,\n        low: candles[i-2].high,\n        timeframe: tf,\n        filled: candles_1m.length > 0 && candles_1m[candles_1m.length-1].low <= candles[i-2].high,\n        time: candles[i].time\n      });\n    }\n    if (candles[i].high < candles[i-2].low) {\n      fvgs.push({\n        type: 'BEARISH',\n        high: candles[i-2].low,\n        low: candles[i].high,\n        timeframe: tf,\n        filled: candles_1m.length > 0 && candles_1m[candles_1m.length-1].high >= candles[i-2].low,\n        time: candles[i].time\n      });\n    }\n  }\n  return fvgs;\n}\n\n// Order Blocks\nfunction findOrderBlocks(candles, tf) {\n  const obs = [];\n  for (let i = 1; i < candles.length - 1; i++) {\n    const curr = candles[i];\n    const next = candles[i+1];\n    const currBearish = curr.close < curr.open;\n    const currBullish = curr.close > curr.open;\n    const nextBigMove = Math.abs(next.close - next.open) > Math.abs(curr.close - curr.open) * 1.5;\n    \n    if (currBearish && next.close > next.open && nextBigMove) {\n      obs.push({ type: 'BULLISH', high: curr.open, low: curr.close, timeframe: tf, tested: false, time: curr.time });\n    }\n    if (currBullish && next.close < next.open && nextBigMove) {\n      obs.push({ type: 'BEARISH', high: curr.close, low: curr.open, timeframe: tf, tested: false, time: curr.time });\n    }\n  }\n  return obs;\n}\n\n// Market Structure (HH/HL/LH/LL)\nfunction detectMarketStructure(swings) {\n  const { swingHighs, swingLows } = swings;\n  if (swingHighs.length < 2 || swingLows.length < 2) return \"NEUTRAL\";\n  const lastH = swingHighs.slice(-2);\n  const lastL = swingLows.slice(-2);\n  const hh = lastH[1].price > lastH[0].price;\n  const hl = lastL[1].price > lastL[0].price;\n  const lh = lastH[1].price < lastH[0].price;\n  const ll = lastL[1].price < lastL[0].price;\n  if (hh && hl) return \"BULLISH\";\n  if (lh && ll) return \"BEARISH\";\n  return \"NEUTRAL\";\n}\n\n// SFP Detection\nfunction detectSFP(candles, swings) {\n  const sfps = [];\n  const { swingHighs, swingLows } = swings;\n  const last5 = candles.slice(-5);\n  \n  for (const c of last5) {\n    for (const sl of swingLows) {\n      if (c.low < sl.price && c.close > sl.price) {\n        sfps.push({ type: 'BULLISH', price: sl.price, candle_time: c.time, timeframe: '5m' });\n      }\n    }\n    for (const sh of swingHighs) {\n      if (c.high > sh.price && c.close < sh.price) {\n        sfps.push({ type: 'BEARISH', price: sh.price, candle_time: c.time, timeframe: '5m' });\n      }\n    }\n  }\n  return sfps;\n}\n\n// Equal Highs/Lows\nfunction detectEqualHL(swings, tolerance) {\n  const result = [];\n  const { swingHighs, swingLows } = swings;\n  \n  for (let i = 0; i < swingHighs.length; i++) {\n    let count = 1;\n    for (let j = i + 1; j < swingHighs.length; j++) {\n      if (Math.abs(swingHighs[i].price - swingHighs[j].price) <= tolerance) count++;\n    }\n    if (count >= 2) result.push({ type: 'EQUAL_HIGHS', price: swingHighs[i].price, count });\n  }\n  for (let i = 0; i < swingLows.length; i++) {\n    let count = 1;\n    for (let j = i + 1; j < swingLows.length; j++) {\n      if (Math.abs(swingLows[i].price - swingLows[j].price) <= tolerance) count++;\n    }\n    if (count >= 2) result.push({ type: 'EQUAL_LOWS', price: swingLows[i].price, count });\n  }\n  return result;\n}\n\n// Opening Range\nfunction calcOpeningRange(candles1m) {\n  const orCandles = candles1m.filter(c => {\n    const time = new Date(c.time);\n    const etH = time.getUTCHours() - 5;\n    const etM = time.getUTCMinutes();\n    return etH === 9 && etM >= 30 && etM < 45;\n  });\n  if (orCandles.length === 0) return { high: 0, low: 0 };\n  return {\n    high: Math.max(...orCandles.map(c => c.high)),\n    low: Math.min(...orCandles.map(c => c.low))\n  };\n}\n\n// === CALCULATE EVERYTHING ===\nconst closes1m = candles_1m.map(c => c.close);\nconst closes5m = candles_5m.map(c => c.close);\n\nconst ema9_1m = calcEMA(closes1m, 9);\nconst ema21_1m = calcEMA(closes1m, 21);\nconst ema50_1m = calcEMA(closes1m, 50);\nconst ema9_5m = calcEMA(closes5m, 9);\nconst ema21_5m = calcEMA(closes5m, 21);\n\nconst rsi_1m = calcRSI(closes1m, 14);\nconst atr_1m = calcATR(candles_1m, 14);\nconst atr_5m = calcATR(candles_5m, 14);\nconst bb_1m = calcBB(closes1m, 20, 2);\nconst vwap = calcVWAP(candles_1m);\nconst volumeDelta = calcVolumeDelta(candles_1m);\nconst avgVolume = candles_1m.length > 0 ? candles_1m.reduce((s, c) => s + c.volume, 0) / candles_1m.length : 0;\n\nconst swings5m = findSwings(candles_5m, 3);\nconst swings1m = findSwings(candles_1m, 5);\nconst fvgs5m = findFVGs(candles_5m, '5m');\nconst fvgs1m = findFVGs(candles_1m, '1m');\nconst orderBlocks5m = findOrderBlocks(candles_5m, '5m');\nconst marketStructure5m = detectMarketStructure(swings5m);\nconst sfps = detectSFP(candles_5m, swings5m);\nconst equalHL = detectEqualHL(swings5m, atr_5m * 0.2);\nconst openingRange = calcOpeningRange(candles_1m);\n\nconst supports = swings1m.swingLows.slice(-5).map(s => ({ price: s.price, time: s.time }));\nconst resistances = swings1m.swingHighs.slice(-5).map(s => ({ price: s.price, time: s.time }));\n\nconst indicators = {\n  ema9: ema9_1m.value,\n  ema21: ema21_1m.value,\n  ema50: ema50_1m.value,\n  ema9_series: ema9_1m.series.slice(-10),\n  ema21_series: ema21_1m.series.slice(-10),\n  ema9_5m: ema9_5m.value,\n  ema21_5m: ema21_5m.value,\n  rsi: rsi_1m,\n  atr: atr_1m,\n  atr5m: atr_5m,\n  atrAvg: atr_1m,\n  bollingerBands: bb_1m,\n  vwap: vwap,\n  volumeDelta: volumeDelta.slice(-20),\n  cumulativeDelta: volumeDelta.length > 0 ? volumeDelta[volumeDelta.length-1].cumDelta : 0,\n  avgVolume: avgVolume,\n  supports: supports,\n  resistances: resistances,\n  fairValueGaps: [...fvgs5m, ...fvgs1m].slice(-15),\n  orderBlocks: orderBlocks5m.slice(-5),\n  liquidityLevels: equalHL,\n  marketStructure: { '5m': marketStructure5m },\n  swingFailurePatterns: sfps,\n  equalHighsLows: equalHL,\n  openingRange: openingRange\n};\n\nconst symbol = $('Get Market Data').first().json.symbol_mnq;\n\n// Parse MGC candles\nfunction parseCandlesMGC(data) {\n  const values = data?.values || data?.body?.values || [];\n  return values.reverse().map(v => ({\n    time: v.datetime,\n    open: parseFloat(v.open),\n    high: parseFloat(v.high),\n    low: parseFloat(v.low),\n    close: parseFloat(v.close),\n    volume: parseInt(v.volume || 0)\n  }));\n}\n\nconst mgc_candles_1m = parseCandlesMGC(mgcCandles1mRaw);\nconst mgc_candles_5m = parseCandlesMGC(mgcCandles5mRaw);\n\nreturn [{\n  json: {\n    indicators,\n    candles_1m,\n    candles_5m,\n    candles_daily: [],\n    candles_4h: [],\n    mgc_candles_1m,\n    mgc_candles_5m,\n    positions: $('HTTP Get Positions').first().json || [],\n    config: $('Get Config').first().json,\n    symbol,\n    symbol_mgc: $('Get Market Data').first().json.symbol_mgc,\n    shouldFlatten,\n    noNewPositions,\n    accessToken: $('Merge Auth').first().json.accessToken,\n    accountId: ($('HTTP Get Account').first().json || [])[0]?.id || 0,\n    accountSpec: ($('HTTP Get Account').first().json || [])[0]?.name || ''\n  }\n}];"
      },
      "id": "b4c5d6e7-f8a9-0123-abcd-234567890abc",
      "name": "Calculate Indicators",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2200,
        0
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.SESSION_AGENT_WORKFLOW_ID || 'BK6ybQX7wBErUfzo' }}",
        "mode": "each",
        "options": {}
      },
      "id": "c5d6e7f8-a9b0-1234-bcde-345678901bcd",
      "name": "Layer 1: Session Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        2420,
        -200
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.CORRELATION_AGENT_WORKFLOW_ID || 'j2U5LCMVRG1pYQYW' }}",
        "mode": "each",
        "options": {}
      },
      "id": "d6e7f8a9-b0c1-2345-cdef-456789012cde",
      "name": "Layer 1: Correlation Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        2420,
        0
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.NEWS_AGENT_WORKFLOW_ID || 'aiDx8Q4nDoAMqaqb' }}",
        "mode": "each",
        "options": {}
      },
      "id": "e7f8a9b0-c1d2-3456-defa-567890123def",
      "name": "Layer 1: News Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        2420,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// Check Layer 1 results - should we proceed to Layer 2?\nconst sessionSignal = $('Layer 1: Session Agent').first().json;\nconst correlationSignal = $('Layer 1: Correlation Agent').first().json;\nconst newsSignal = $('Layer 1: News Agent').first().json;\n\nconst session = sessionSignal.session || {};\n\n// GATE CONDITIONS - stop if any of these:\n// 1. Bot outside trading hours for this asset\nif (!session.shouldTrade) {\n  return []; // stop\n}\n\n// 2. News veto (high impact event nearby)\nif (newsSignal.urgency === 'HIGH' && newsSignal.signal === 'HOLD') {\n  return [{\n    json: {\n      proceed: false,\n      reason: 'NEWS_VETO',\n      newsSignal,\n      sessionSignal,\n      correlationSignal,\n      layer1: [sessionSignal, correlationSignal, newsSignal]\n    }\n  }];\n}\n\n// 3. Lunch hour\nif (session.current === 'LUNCH') {\n  return []; // stop\n}\n\n// 4. Flatten warning\nif (session.flattenWarning) {\n  return [{\n    json: {\n      proceed: false,\n      reason: 'FLATTEN_WARNING',\n      flattenMinutes: session.flattenMinutes,\n      layer1: [sessionSignal, correlationSignal, newsSignal]\n    }\n  }];\n}\n\n// All clear - proceed to Layer 2\nreturn [{\n  json: {\n    proceed: true,\n    recommendedStrategies: session.recommendedStrategies || [],\n    avoidStrategies: session.avoidStrategies || [],\n    killZoneActive: session.killZoneActive || false,\n    killZone: session.killZone || 'NONE',\n    macroBias: correlationSignal.macroBias || 'NEUTRAL',\n    vixRegime: correlationSignal.vixRegime || 'NORMAL',\n    layer1: [sessionSignal, correlationSignal, newsSignal]\n  }\n}];"
      },
      "id": "f8a9b0c1-d2e3-4567-efab-678901234efa",
      "name": "Layer 1 Gate",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2640,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-proceed",
              "leftValue": "={{ $json.proceed }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "a9b0c1d2-e3f4-5678-abcd-789012345abc",
      "name": "IF Proceed to Layer 2",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2860,
        0
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.ICT_AGENT_WORKFLOW_ID || 'Km5Wty5vyEawreXQ' }}",
        "mode": "each",
        "options": {}
      },
      "id": "b0c1d2e3-f4a5-6789-bcde-890123456bcd",
      "name": "Layer 2: ICT Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        3080,
        -300
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.VOLUME_AGENT_WORKFLOW_ID || 'yhE0Mnn94e8XFHHT' }}",
        "mode": "each",
        "options": {}
      },
      "id": "c1d2e3f4-a5b6-7890-cdef-901234567cde",
      "name": "Layer 2: Volume Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        3080,
        -100
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.TECHNICAL_AGENT_WORKFLOW_ID || 'QwVYR6gWpN6p14mc' }}",
        "mode": "each",
        "options": {}
      },
      "id": "d2e3f4a5-b6c7-8901-defa-012345678def",
      "name": "Layer 2: Technical Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        3080,
        100
      ]
    },
    {
      "parameters": {
        "source": "parameter",
        "workflowId": "={{ $env.FIBONACCI_AGENT_WORKFLOW_ID || 'Ej5F6JsfGwrruKOd' }}",
        "mode": "each",
        "options": {}
      },
      "id": "e3f4a5b6-c7d8-9012-efab-123456789efa",
      "name": "Layer 2: Fibonacci Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        3080,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Merge Layer 1 + Layer 2 signals\nconst layer1 = $('Layer 1 Gate').first().json.layer1 || [];\nconst ictSignal = $('Layer 2: ICT Agent').first().json;\nconst volumeSignal = $('Layer 2: Volume Agent').first().json;\nconst technicalSignal = $('Layer 2: Technical Agent').first().json;\nconst fibSignal = $('Layer 2: Fibonacci Agent').first().json;\n\nconst allSignals = [...layer1, ictSignal, volumeSignal, technicalSignal, fibSignal];\nconst layer1Data = $('Layer 1 Gate').first().json;\n\n// Summary for Master Agent\nconst signalSummary = allSignals.map(s => ({\n  agent: s.agent,\n  signal: s.signal,\n  confidence: s.confidence,\n  strategy: s.strategy,\n  reasoning: s.reasoning,\n  entry: s.entry,\n  stopLoss: s.stopLoss,\n  takeProfit: s.takeProfit,\n  riskReward: s.riskReward,\n  urgency: s.urgency,\n  killZone: s.killZone\n}));\n\n// Count agreements\nconst buySignals = allSignals.filter(s => s.signal === 'BUY' && s.confidence > 0.5);\nconst sellSignals = allSignals.filter(s => s.signal === 'SELL' && s.confidence > 0.5);\n\nreturn [{\n  json: {\n    signals: signalSummary,\n    buyCount: buySignals.length,\n    sellCount: sellSignals.length,\n    holdCount: allSignals.filter(s => s.signal === 'HOLD').length,\n    recommendedStrategies: layer1Data.recommendedStrategies,\n    avoidStrategies: layer1Data.avoidStrategies,\n    killZoneActive: layer1Data.killZoneActive,\n    macroBias: layer1Data.macroBias,\n    vixRegime: layer1Data.vixRegime,\n    symbol: $('Calculate Indicators').first().json.symbol,\n    accountId: $('Calculate Indicators').first().json.accountId,\n    accountSpec: $('Calculate Indicators').first().json.accountSpec,\n    accessToken: $('Calculate Indicators').first().json.accessToken,\n    config: $('Calculate Indicators').first().json.config\n  }\n}];"
      },
      "id": "f4a5b6c7-d8e9-0123-fabc-234567890fab",
      "name": "Merge All Signals",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3300,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.anthropic.com/v1/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{ $env.ANTHROPIC_API_KEY || '' }}"
            },
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ model: 'claude-sonnet-4-20250514', max_tokens: 1024, system: 'Voce e o MASTER TRADER, um orquestrador que recebe sinais de 7 agentes especialistas e decide a acao final.\\n\\nARQUITETURA DE 3 CAMADAS:\\n- Camada 1 (Filtros): Session, Correlation, News - fornecem contexto\\n- Camada 2 (Analistas): ICT, Volume, Technical, Fibonacci - geram sinais de trade\\n- Voce e a Camada 3 (Decisor): pondera tudo e decide\\n\\nREGRAS DE DECISAO:\\n1. Se 3+ analistas (Layer 2) concordam na direcao -> alta confianca, executar se R:R >= 2\\n2. Se 2 analistas concordam com confianca > 0.75 -> executar se R:R >= 2.5\\n3. Se apenas 1 analista com confianca > 0.90 -> executar se R:R >= 3\\n4. Se analistas conflitam (BUY vs SELL) -> HOLD\\n5. Se News Agent sinalizou HIGH urgency -> HOLD absoluto\\n6. Se Correlation/macro bias contradiz os sinais -> reduzir confianca em 20%\\n7. Se Kill Zone ativa -> aumentar peso do ICT Agent em 20%\\n8. Se VIX regime e HIGH_FEAR -> favorecer sinais SHORT para MNQ, LONG para MGC\\n\\nPESOS DOS ANALISTAS:\\n- ICT Agent: 30% (35% em Kill Zone)\\n- Volume Agent: 25%\\n- Technical Agent: 25%\\n- Fibonacci Agent: 20%\\n\\nUSE SL/TP DO ANALISTA COM MAIOR CONFIANCA quando houver consenso.\\n\\nConsidere tambem:\\n- recommendedStrategies e avoidStrategies do Session Agent\\n- macroBias do Correlation Agent\\n\\nRESPONDA SOMENTE com JSON:\\n{\\n  \"action\": \"BUY | SELL | HOLD\",\\n  \"symbol\": \"<symbol>\",\\n  \"qty\": <number>,\\n  \"entry\": <price>,\\n  \"stopLoss\": <price>,\\n  \"takeProfit\": <price>,\\n  \"agentsAgreed\": [\"ICT\", \"VOLUME\"],\\n  \"masterConfidence\": 0.82,\\n  \"reasoning\": \"<explanation of decision>\",\\n  \"riskPerTrade\": <dollar amount>,\\n  \"strategy\": \"<primary strategy used>\"\\n}', messages: [{ role: 'user', content: JSON.stringify($json) }] }) }}"
      },
      "id": "a5b6c7d8-e9f0-1234-abcd-345678901abc",
      "name": "Master Claude Decision",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3520,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const response = $input.first().json;\nconst content = response.content?.[0]?.text || response.body?.content?.[0]?.text || '{}';\n\nlet decision;\ntry {\n  const jsonMatch = content.match(/\\{[\\s\\S]*\\}/);\n  decision = jsonMatch ? JSON.parse(jsonMatch[0]) : JSON.parse(content);\n} catch (e) {\n  decision = { action: \"HOLD\", reasoning: \"Parse error: \" + e.message };\n}\n\ndecision.action = [\"BUY\", \"SELL\", \"HOLD\"].includes(decision.action) ? decision.action : \"HOLD\";\ndecision.symbol = decision.symbol || $('Merge All Signals').first().json.symbol;\ndecision.accountId = $('Merge All Signals').first().json.accountId;\ndecision.accountSpec = $('Merge All Signals').first().json.accountSpec;\ndecision.accessToken = $('Merge All Signals').first().json.accessToken;\ndecision.config = $('Merge All Signals').first().json.config;\n\n// Check flatten/noNewPositions flags from Calculate Indicators\nconst shouldFlatten = $('Calculate Indicators').first().json.shouldFlatten;\nconst noNewPositions = $('Calculate Indicators').first().json.noNewPositions;\n\n// If shouldFlatten - override to close all positions\nif (shouldFlatten) {\n  decision.action = 'FLATTEN';\n  decision.reasoning = 'FLATTEN: 3:55 PM CT - closing all positions before session end (prop firm rule)';\n}\n// If noNewPositions - block new trades\nelse if (noNewPositions && decision.action !== 'HOLD') {\n  decision.action = 'HOLD';\n  decision.reasoning = 'BLOCKED: No new positions after 3:50 PM CT - too close to session end';\n}\n\ndecision.shouldFlatten = shouldFlatten;\ndecision.noNewPositions = noNewPositions;\n\nreturn [{ json: decision }];"
      },
      "id": "b6c7d8e9-f0a1-2345-bcde-456789012bcd",
      "name": "Parse Master Decision",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3740,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-execute",
              "leftValue": "={{ $json.action === 'BUY' || $json.action === 'SELL' || $json.action === 'FLATTEN' }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "c7d8e9f0-a1b2-3456-cdef-567890123cde",
      "name": "IF Execute Trade",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        3960,
        0
      ]
    },
    {
      "parameters": {
        "source": "database",
        "workflowId": "={{ $env.RISK_MASTER_WORKFLOW_ID || 'ZDFUioPIsSM4eZ5D' }}",
        "workflowInputs": {
          "mappingMode": "defineBelow",
          "value": {
            "masterDecision": "={{ $json }}",
            "accountInfo": "={{ $('HTTP Get Account').first().json }}",
            "positions": "={{ $('HTTP Get Positions').first().json }}",
            "todayPnL": "={{ $('Risk Manager')?.first()?.json?.totalPnL || 0 }}",
            "todayTrades": "={{ $('Risk Manager')?.first()?.json?.tradesThisDay || 0 }}",
            "config": "={{ $('Get Config').first().json }}",
            "tradeHistory": "={{ $getWorkflowStaticData('global').tradeHistory || [] }}"
          }
        }
      },
      "id": "rm-a1b2c3d4-risk-master-node",
      "name": "Risk Master",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        4180,
        -100
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-risk-approved",
              "leftValue": "={{ $json.approved }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "rm-b2c3d4e5-if-risk-approved",
      "name": "IF Risk Approved",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        4400,
        -100
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $env.TELEGRAM_CHAT_ID || '' }}",
        "text": "=\u26d4 *TRADE REJEITADO pelo Risk Master*\n\nSinal: {{ $('Parse Master Decision').first().json.action }} {{ $('Parse Master Decision').first().json.symbol }}\nMotivo: {{ $json.reason }}\n\n\ud83d\udcca Risk Report:\n- Drawdown: {{ $json.riskReport.drawdownUsed }}\n- Trades hoje: {{ $json.riskReport.tradesToday }}\n- Posi\u00e7\u00f5es abertas: {{ $json.riskReport.openPositions }}\n- Losses consecutivos: {{ $json.riskReport.consecutiveLosses }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "rm-c3d4e5f6-telegram-rejected",
      "name": "Telegram Risk Rejected",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        4620,
        100
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "id": "d8e9f0a1-b2c3-4567-defa-678901234def",
      "name": "Place Bracket Order",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4620,
        -100
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst decision = $('Parse Master Decision').first().json;\nconst positions = $('HTTP Get Positions').first().json || [];\n\n// Track daily P&L\nconst today = new Date().toISOString().split('T')[0];\nif (staticData.lastTradeDay !== today) {\n  staticData.dailyPnL = 0;\n  staticData.tradesThisDay = 0;\n  staticData.lastTradeDay = today;\n}\n\n// Calculate current P&L from positions\nlet currentPnL = 0;\nfor (const pos of positions) {\n  currentPnL += pos.pnl || pos.openPL || 0;\n}\n\nconst totalPnL = (staticData.dailyPnL || 0) + currentPnL;\nconst maxDrawdown = decision.config?.maxDrawdownMNQ || 500;\n\nlet alert = null;\nlet closeAll = false;\n\nif (totalPnL < -maxDrawdown) {\n  alert = `DRAWDOWN LIMIT HIT: $${totalPnL.toFixed(2)} exceeds max $${maxDrawdown}. Closing all positions.`;\n  closeAll = true;\n  staticData.botActive = false;\n} else if (totalPnL < -maxDrawdown * 0.7) {\n  alert = `WARNING: P&L at $${totalPnL.toFixed(2)}, approaching max drawdown of $${maxDrawdown}`;\n}\n\nif (decision.action !== 'HOLD') {\n  staticData.tradesThisDay = (staticData.tradesThisDay || 0) + 1;\n}\n\nreturn [{\n  json: {\n    totalPnL,\n    maxDrawdown,\n    alert,\n    closeAll,\n    tradesThisDay: staticData.tradesThisDay,\n    decision\n  }\n}];"
      },
      "id": "e9f0a1b2-c3d4-5678-efab-789012345efa",
      "name": "Risk Manager",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4400,
        -100
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-closeall",
              "leftValue": "={{ $json.closeAll }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "f0a1b2c3-d4e5-6789-fabc-890123456fab",
      "name": "IF Close All",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        4620,
        -100
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://demo.tradovateapi.com/v1/order/liquidateposition",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('Parse Master Decision').first().json.accessToken }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ accountId: $('Parse Master Decision').first().json.accountId }) }}"
      },
      "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
      "name": "Close All Positions",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4840,
        -200
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $env.TELEGRAM_CHAT_ID || '' }}",
        "text": "=\ud83d\udea8 *DRAWDOWN ALERT*\n\n{{ $('Risk Manager').first().json.alert }}\n\nAll positions liquidated. Bot paused.\nUse /start to reactivate.",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "b2c3d4e5-f6a7-8901-2345-678901abcdef",
      "name": "Telegram Alert Drawdown",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        5060,
        -200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $env.TELEGRAM_CHAT_ID || '' }}",
        "text": "=\ud83e\udd16 *TRADE EXECUTED*\n\nSymbol: {{ $('Parse Master Decision').first().json.symbol }}\nAction: {{ $('Parse Master Decision').first().json.action }}\nQty: {{ $('Parse Master Decision').first().json.qty }}\nEntry: {{ $('Parse Master Decision').first().json.entry }}\nSL: {{ $('Parse Master Decision').first().json.stopLoss }}\nTP: {{ $('Parse Master Decision').first().json.takeProfit }}\nConfidence: {{ $('Parse Master Decision').first().json.masterConfidence }}\n\nAgents: {{ $('Parse Master Decision').first().json.agentsAgreed?.join(', ') }}\nStrategy: {{ $('Parse Master Decision').first().json.strategy }}\n\nReasoning: {{ $('Parse Master Decision').first().json.reasoning }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "c3d4e5f6-a7b8-9012-3456-789012abcdef",
      "name": "Telegram Notify",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        4180,
        100
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "updates": [
          "message"
        ]
      },
      "id": "d4e5f6a7-b8c9-0123-4567-890123abcdef",
      "name": "Telegram Commands",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        600
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "rules": [
            {
              "value": "/status",
              "outputKey": "status",
              "operation": "startsWith"
            },
            {
              "value": "/config",
              "outputKey": "config",
              "operation": "startsWith"
            },
            {
              "value": "/stop",
              "outputKey": "stop",
              "operation": "startsWith"
            },
            {
              "value": "/start",
              "outputKey": "start",
              "operation": "startsWith"
            },
            {
              "value": "/agents",
              "outputKey": "agents",
              "operation": "startsWith"
            }
          ]
        },
        "dataPropertyName": "={{ $json.message?.text || '' }}"
      },
      "id": "e5f6a7b8-c9d0-1234-5678-901234abcdef",
      "name": "Switch Commands",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        220,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst response = `\\ud83d\\udcca *BOT STATUS*\\n\\nActive: ${staticData.botActive !== false ? '\\u2705' : '\\u274c'}\\nDaily P&L: $${(staticData.dailyPnL || 0).toFixed(2)}\\nTrades Today: ${staticData.tradesThisDay || 0}\\nMax Drawdown: $${staticData.maxDrawdownMNQ || 500}\\n\\nMNQ Qty: ${staticData.maxQtyMNQ || 1}\\nMGC Qty: ${staticData.maxQtyMGC || 1}`;\nreturn [{ json: { text: response } }];"
      },
      "id": "f6a7b8c9-d0e1-2345-6789-012345abcdef",
      "name": "Handle Status",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst msg = $input.first().json.message?.text || '';\nconst parts = msg.split(' ');\n// /config MNQ 2 or /config MGC 1\nif (parts.length >= 3) {\n  const asset = parts[1].toUpperCase();\n  const qty = parseInt(parts[2]);\n  if (asset === 'MNQ') staticData.maxQtyMNQ = qty;\n  else if (asset === 'MGC') staticData.maxQtyMGC = qty;\n  return [{ json: { text: `\\u2705 ${asset} qty set to ${qty}` } }];\n}\nreturn [{ json: { text: '\\u274c Usage: /config MNQ 2 or /config MGC 1' } }];"
      },
      "id": "a7b8c9d0-e1f2-3456-7890-123456abcdef",
      "name": "Handle Config",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        550
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nstaticData.botActive = false;\nreturn [{ json: { text: '\\ud83d\\uded1 Bot STOPPED. Use /start to reactivate.' } }];"
      },
      "id": "b8c9d0e1-f2a3-4567-8901-234567abcdef",
      "name": "Handle Stop",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        700
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nstaticData.botActive = true;\nreturn [{ json: { text: '\\u2705 Bot STARTED. Trading active.' } }];"
      },
      "id": "c9d0e1f2-a3b4-5678-9012-345678abcdef",
      "name": "Handle Start",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        850
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst agents = staticData.activeAgents || ['ICT', 'VOLUME', 'TECHNICAL', 'NEWS', 'FIBONACCI', 'CORRELATION', 'SESSION'];\nconst msg = $input.first().json.message?.text || '';\nconst parts = msg.split(' ');\nif (parts.length >= 3) {\n  const agent = parts[1].toUpperCase();\n  const action = parts[2].toLowerCase();\n  if (action === 'off') {\n    staticData.activeAgents = agents.filter(a => a !== agent);\n    return [{ json: { text: `\\u274c ${agent} agent DISABLED` } }];\n  } else if (action === 'on') {\n    if (!agents.includes(agent)) agents.push(agent);\n    staticData.activeAgents = agents;\n    return [{ json: { text: `\\u2705 ${agent} agent ENABLED` } }];\n  }\n}\nreturn [{ json: { text: `\\ud83e\\udd16 *AGENTS*\\n\\n${agents.map(a => `\\u2022 ${a}: \\u2705`).join('\\n')}` } }];"
      },
      "id": "d0e1f2a3-b4c5-6789-0123-456789abcdef",
      "name": "Handle Agents",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        1000
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $input.first().json.message?.chat?.id || $env.TELEGRAM_CHAT_ID || '' }}",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "e1f2a3b4-c5d6-7890-1234-567890abcdef",
      "name": "Telegram Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        660,
        700
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Check Trading Hours",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Trading Hours": {
      "main": [
        [
          {
            "node": "Auth Manager",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auth Manager": {
      "main": [
        [
          {
            "node": "IF Needs Auth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Needs Auth": {
      "main": [
        [
          {
            "node": "HTTP Auth Tradovate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge Auth",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "HTTP Auth Tradovate": {
      "main": [
        [
          {
            "node": "Cache Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cache Token": {
      "main": [
        [
          {
            "node": "Merge Auth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Auth": {
      "main": [
        [
          {
            "node": "HTTP Get Account",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Get Positions",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Get Account": {
      "main": [
        [
          {
            "node": "Get Market Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Get Positions": {
      "main": [
        [
          {
            "node": "Get Market Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Config": {
      "main": [
        [
          {
            "node": "Get Market Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Market Data": {
      "main": [
        [
          {
            "node": "HTTP MNQ 1m",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MNQ 5m",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MGC 1m",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MGC 5m",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MGC 1m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MGC 5m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MNQ 1m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MNQ 5m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Indicators": {
      "main": [
        [
          {
            "node": "Layer 1: Session Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 1: Correlation Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 1: News Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1: Session Agent": {
      "main": [
        [
          {
            "node": "Layer 1 Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1: Correlation Agent": {
      "main": [
        [
          {
            "node": "Layer 1 Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1: News Agent": {
      "main": [
        [
          {
            "node": "Layer 1 Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1 Gate": {
      "main": [
        [
          {
            "node": "IF Proceed to Layer 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Proceed to Layer 2": {
      "main": [
        [
          {
            "node": "Layer 2: ICT Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 2: Volume Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 2: Technical Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 2: Fibonacci Agent",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Layer 2: ICT Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: Volume Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: Technical Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: Fibonacci Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Signals": {
      "main": [
        [
          {
            "node": "Master Claude Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Master Claude Decision": {
      "main": [
        [
          {
            "node": "Parse Master Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Master Decision": {
      "main": [
        [
          {
            "node": "IF Execute Trade",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Execute Trade": {
      "main": [
        [
          {
            "node": "Risk Master",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Risk Master": {
      "main": [
        [
          {
            "node": "IF Risk Approved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Risk Approved": {
      "main": [
        [
          {
            "node": "Place Bracket Order",
            "type": "main",
            "index": 0
          },
          {
            "node": "Telegram Notify",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Telegram Risk Rejected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Place Bracket Order": {
      "main": [
        [
          {
            "node": "Risk Manager",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Risk Manager": {
      "main": [
        [
          {
            "node": "IF Close All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Close All": {
      "main": [
        [
          {
            "node": "Close All Positions",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Close All Positions": {
      "main": [
        [
          {
            "node": "Telegram Alert Drawdown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Commands": {
      "main": [
        [
          {
            "node": "Switch Commands",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch Commands": {
      "main": [
        [
          {
            "node": "Handle Status",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Config",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Stop",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Start",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Agents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Status": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Config": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Stop": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Start": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Agents": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": ""
  },
  "versionId": "1",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "trading-bot",
      "createdAt": "2024-01-01T00:00:00.000Z",
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  ]
}