{
  "id": "qn0IYQwkkqWmmzQB",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "\ud83d\udcc8 Daily Nifty Swing Trade Signal Bot",
  "tags": [],
  "nodes": [
    {
      "id": "57793e93-5594-4171-9620-3fc21ec3c89b",
      "name": "Fetch Quote via Rapid API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        0,
        -64
      ],
      "parameters": {
        "url": "=https://apidojo-yahoo-finance-v1.p.rapidapi.com/market/v2/get-quotes?region=IN&symbols={{$json[\"ticker\"]}}\n",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "value": "={   \"symbols\": [{{$json[\"ticker\"]}}],   \"proxyConfig\": { \"useApifyProxy\": true } }"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "x-rapidapi-host",
              "value": "apidojo-yahoo-finance-v1.p.rapidapi.com"
            },
            {
              "name": "x-rapidapi-key\t",
              "value": "<Your API key>"
            },
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9250c09c-d2a0-4329-99e3-9b8af37ead97",
      "name": "Split Trade Recommendations",
      "type": "n8n-nodes-base.code",
      "position": [
        1248,
        -64
      ],
      "parameters": {
        "jsCode": "const messages = $json.message.content;\n\nlet parsed;\ntry {\n  parsed = JSON.parse(messages.match(/```json([\\s\\S]*?)```/)[1].trim());\n} catch (e) {\n  throw new Error(\"Failed to parse OpenAI JSON output. Make sure it is enclosed in ```json ... ```.\");\n}\n\nreturn parsed.map(item => ({ json: item }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "7d71fd77-1fc1-4805-9763-1d9e275c2932",
      "name": "Generate Swing Trade Ideas (OpenAI)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        880,
        -64
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "chatgpt-4o-latest",
          "cachedResultName": "CHATGPT-4O-LATEST"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a trading assistant for Indian equities. Only use the data provided to generate potential profitable swing trade setups. Do not assume or invent any details."
            },
            {
              "content": "={{$json.prompt}}"
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "8027fc86-2d78-4729-b474-6557f474b049",
      "name": "Log Trade to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1728,
        -144
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ new Date().toLocaleString(\"en-IN\", { timeZone: \"Asia/Kolkata\" }) }}\n",
            "Entry": "={{$json.entry}}\n",
            "Reason": "={{$json.reason}}\n",
            "Status": "=Open\n",
            "Symbol": "={{$json.symbol}}\n",
            "Target": "={{$json.target}}\n",
            "Direction": "={{$json.direction}}",
            "Stop Loss": "={{$json.stopLoss}}\n",
            "Time Frame": "={{$json.timeFrame}}\n"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Symbol",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Symbol",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Direction",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Direction",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entry",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Entry",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Target",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Target",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Stop Loss",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Stop Loss",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Time Frame",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Time Frame",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reason",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "pnl",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "pnl",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "currentPrice",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "currentPrice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "lastChecked",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "lastChecked",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "rowIndex",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "rowIndex",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "pnlColor",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "pnlColor",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "Your google sheet",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1HwZFAfdrRzqDiWcf7eIZFORhFlzr2GxJEVhvs3vnuBI",
          "cachedResultUrl": "Your Google Sheet",
          "cachedResultName": "Trade_Recommendations_Tracker"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "0b1b7435-f0d0-4da5-a89c-ee3642d36ad4",
      "name": "Send Trade Alert to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1568,
        48
      ],
      "parameters": {
        "text": "=\ud83d\udcca *{{$json.symbol}}* | {{$json.direction}}\n\ud83d\udcb8 Entry: \u20b9{{$json.entry}} | \ud83c\udfaf Target: \u20b9{{$json.target}} | \ud83d\uded1 SL: \u20b9{{$json.stopLoss}}\n\u23f3 {{$json.timeFrame}}\n\ud83e\udde0 {{$json.reason}}\n",
        "chatId": "Your chat Id",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "9f48a5f8-fa17-4c76-9bfd-56160b055d0a",
      "name": "\u2705 Trigger - Daily Market Close\t",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -448,
        -64
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1,
                2,
                3,
                4,
                5,
                6,
                0
              ],
              "triggerAtHour": 16,
              "triggerAtMinute": 5
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0cdcc80a-5ae4-45e3-94a0-368af8cb57dd",
      "name": "\ud83d\udd22 Prepare Stock List (NSE 100)\t",
      "type": "n8n-nodes-base.code",
      "position": [
        -224,
        -64
      ],
      "parameters": {
        "jsCode": "const tickers = [\n  \"TCS.NS\", \"RELIANCE.NS\", \"INFY.NS\", \"HDFCBANK.NS\"\n  // (Add more if needed up to 100)\n];\n\nreturn tickers.map(ticker => ({\n  json: { ticker }\n}));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b7452ca2-852c-446c-addb-31978642f6dc",
      "name": "\ud83e\uddee Format EOD Data\t",
      "type": "n8n-nodes-base.code",
      "position": [
        224,
        -64
      ],
      "parameters": {
        "jsCode": "const output = [];\n\nfor (const item of items) {\n  const result = item.json.quoteResponse?.result?.[0];\n  if (!result) continue;\n\n  output.push({\n    symbol: result.symbol,\n    name: result.shortName || result.longName || result.symbol,\n    price: result.regularMarketPrice,\n    open: result.regularMarketOpen,\n    high: result.regularMarketDayHigh,\n    low: result.regularMarketDayLow,\n    prevClose: result.regularMarketPreviousClose,\n    volume: result.regularMarketVolume,\n    pe: result.trailingPE,\n    fiftyDayAvg: result.fiftyDayAverage,\n    twoHundredDayAvg: result.twoHundredDayAverage\n  });\n}\n\n// \u2705 This is the correct return format (not wrapped in [])\nreturn {\n  json: {\n    stocks: output.slice(0, 40)  // or however many you want\n  }\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2c04ccba-c395-478c-adef-27efc4bbfb14",
      "name": "\ud83d\udcca Filter Valid Stock Data\t",
      "type": "n8n-nodes-base.code",
      "position": [
        448,
        -64
      ],
      "parameters": {
        "jsCode": "// Extract and flatten stocks array if wrapped in an outer object\nconst input = $json;\nlet stocks = [];\n\nif (Array.isArray(input) && input[0].stocks) {\n  stocks = input[0].stocks;\n} else if (input.stocks) {\n  stocks = input.stocks;\n} else {\n  throw new Error(\"No valid 'stocks' array found in input.\");\n}\n\nreturn [\n  {\n    json: {\n      stocks,\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "aeeba8d3-c27b-44ff-ad43-f9adb92d6aa4",
      "name": "\ud83d\uddc3\ufe0f Build LLM Prompt Input\t",
      "type": "n8n-nodes-base.code",
      "position": [
        672,
        -64
      ],
      "parameters": {
        "jsCode": "const stocks = $json.stocks;\n\nlet formattedStocks = stocks.map(stock => {\n  return `Symbol: ${stock.symbol}\nPrice: \u20b9${stock.price}\nOpen: \u20b9${stock.open}\nHigh: \u20b9${stock.high}\nLow: \u20b9${stock.low}\nPrev Close: \u20b9${stock.prevClose}\nVolume: ${stock.volume}\nPE Ratio: ${stock.pe}\n50DMA: \u20b9${stock.fiftyDayAvg}\n200DMA: \u20b9${stock.twoHundredDayAvg}`;\n}).join(\"\\n\\n\");\n\nreturn [\n  {\n    json: {\n      prompt: `You are a technical analyst. Based only on the EOD data provided below, identify the top 3 swing trades from this list. Return the answer in JSON format with: symbol, direction (Buy/Sell), entry, target, stopLoss, timeFrame, and reason.\\n\\n${formattedStocks}`\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "31271c84-cb7e-49d5-ab71-73b2ddf6ef59",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        160
      ],
      "parameters": {
        "width": 1000,
        "height": 280,
        "content": "\u2502 \ud83d\udcdb Node Name                                  \u2502 \ud83c\udfaf Purpose                                                           \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 \u23f0 Trigger - Daily Market Close               \u2502 Triggers the workflow post EOD (e.g., 4:15 PM IST)                   \u2502\n\u2502 \ud83d\udce6 Prepare Stock List (NSE 100)              \u2502 Generates the list of NSE 100 stock symbols to analyze              \u2502\n\u2502 \ud83c\udf10 Fetch EOD Data (RapidAPI)                 \u2502 Fetches end-of-day stock data from RapidAPI                         \u2502\n\u2502 \ud83d\udee0\ufe0f Format EOD Data                           \u2502 Extracts and formats the quote data from API response               \u2502\n\u2502 \ud83e\uddf9 Filter Valid Stock Data                   \u2502 Filters/cleans/slices usable stock entries                          \u2502\n\u2502 \ud83e\uddfe Build LLM Prompt Input                    \u2502 Converts JSON stock data to string for OpenAI prompt                \u2502\n\u2502 \ud83e\udd16 Generate Swing Trade Ideas (OpenAI)       \u2502 Uses OpenAI to generate top swing trade ideas based on input data   \u2502\n\u2502 \ud83c\udf74 Split JSON Output (Trade-wise)            \u2502 Splits the LLM output into individual trade objects                 \u2502\n\u2502 \ud83d\udcca Save Trade to Google Sheet                \u2502 Appends each trade recommendation to Google Sheet tracker           \u2502\n\u2502 \ud83d\udcf2 Send Telegram Trade Alert                 \u2502 Sends trade alerts to Telegram user in real-time                    "
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cd6dec2a-1cee-4745-903c-0db62aef1447",
  "connections": {
    "\ud83e\uddee Format EOD Data\t": {
      "main": [
        [
          {
            "node": "\ud83d\udcca Filter Valid Stock Data\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Quote via Rapid API": {
      "main": [
        [
          {
            "node": "\ud83e\uddee Format EOD Data\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Trade Recommendations": {
      "main": [
        [
          {
            "node": "Send Trade Alert to Telegram",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Trade to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Trade Alert to Telegram": {
      "main": [
        []
      ]
    },
    "\ud83d\udcca Filter Valid Stock Data\t": {
      "main": [
        [
          {
            "node": "\ud83d\uddc3\ufe0f Build LLM Prompt Input\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\uddc3\ufe0f Build LLM Prompt Input\t": {
      "main": [
        [
          {
            "node": "Generate Swing Trade Ideas (OpenAI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2705 Trigger - Daily Market Close\t": {
      "main": [
        [
          {
            "node": "\ud83d\udd22 Prepare Stock List (NSE 100)\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd22 Prepare Stock List (NSE 100)\t": {
      "main": [
        [
          {
            "node": "Fetch Quote via Rapid API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Swing Trade Ideas (OpenAI)": {
      "main": [
        [
          {
            "node": "Split Trade Recommendations",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}