{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "5988e730-9e46-401d-b52c-281e9acd4bd5",
      "name": "Daily 8AM News Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -192,
        144
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "8f49dc4d-34cf-4f8b-9666-67c34e4c5dd2",
      "name": "Fetch Market News API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        32,
        144
      ],
      "parameters": {
        "url": "https://api.tradient.org/v1/api/market/news",
        "options": {}
      },
      "typeVersion": 4.4
    },
    {
      "id": "197b982e-2ee3-4c99-abcb-aa64eaccad9c",
      "name": "Process News One-by-One",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        928,
        144
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "eeb27fe3-32c2-4d84-9cfb-c11ebd00f78b",
      "name": "Throttle / Rate Limit",
      "type": "n8n-nodes-base.wait",
      "position": [
        1152,
        144
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "52381350-390d-4064-8e84-fab6a47b5e38",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        -496
      ],
      "parameters": {
        "width": 528,
        "height": 480,
        "content": "### STOCK NEWS SENTIMENT AUTOMATION (DAILY - 8 AM)\n\nThis workflow automatically collects, analyzes, and prioritizes stock market news every day at 8 AM.\n\n### How it works:\n\u2022 Fetches the latest market news from an external API  \n\u2022 Selects top recent articles and removes duplicates  \n\u2022 Standardizes key fields (title, content, stock name)  \n\u2022 Processes each news item individually with rate limiting  \n\u2022 Uses Gemini AI to classify sentiment (bullish, bearish, neutral)  \n\u2022 Calculates an impact score based on sentiment & confidence  \n\u2022 Flags high-impact news for alerts  \n\u2022 Stores structured results in Google Sheets  \n \n\n### Setup:\n\u2022 Add Market News API  \n\u2022 Configure Gemini API  \n\u2022 Connect Google Sheets  \n\u2022 Configure Gmail for alerts  \n\u2022 Activate workflow"
      },
      "typeVersion": 1
    },
    {
      "id": "b14c50e0-be1c-4784-968b-a3c23d78614e",
      "name": "Select Top News Articles",
      "type": "n8n-nodes-base.code",
      "position": [
        256,
        144
      ],
      "parameters": {
        "jsCode": "const output = [];\nconst input = $input.first();\n\nfor (const item of input.json.data.latest_news) {\n  output.push(item)\n}\n\nreturn output.slice(0, 2);"
      },
      "typeVersion": 2
    },
    {
      "id": "144f11d6-128a-4178-ae5d-4b5fd490ec3d",
      "name": "Normalize News Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        480,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "92e253cf-3796-4a9b-87fe-9fa8c33e5a18",
              "name": "news_object.text",
              "type": "string",
              "value": "={{ $json.news_object.text }}"
            },
            {
              "id": "d2b27f57-317e-47cd-96f4-b863a3ee22b6",
              "name": "news_object.title",
              "type": "string",
              "value": "={{ $json.news_object.title }}"
            },
            {
              "id": "31d465ec-a6fd-41e2-942c-8df76fbab075",
              "name": "stock_name",
              "type": "string",
              "value": "={{ $json.stock_name }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2545bff7-7782-417a-9f3e-406226ca48b8",
      "name": "Remove Duplicate News",
      "type": "n8n-nodes-base.code",
      "position": [
        704,
        144
      ],
      "parameters": {
        "jsCode": "const seen = new Set();\nconst output = [];\n\nfor (const item of $input.all()) {\n  const title = item.json.news_object.title;\n\n  if (!seen.has(title)) {\n    seen.add(title);\n    output.push(item);\n  }\n}\n\nreturn output;"
      },
      "typeVersion": 2
    },
    {
      "id": "11fedee7-73ad-461c-908a-4b0179877987",
      "name": "Generate Sentiment Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        1376,
        144
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\n\nreturn {\n  json: {\n    prompt: `You are a financial news sentiment analyst.\n\nAnalyze this news:\n\nTitle: ${item.news_object.title}\nContent: ${item.news_object.text}\n\nReturn STRICT JSON:\n\n{\n\"title\": \"${item.news_object.title}\",\n\"stock\": \"${item.stock_name}\",\n\"sentiment\": \"bullish | bearish | neutral\",\n\"confidence\": 0-100,\n\"reason\": \"short explanation\"\n}`\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "aac62391-2b5c-4ccf-8066-db9259f079e4",
      "name": "AI Sentiment Analysis",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "onError": "continueRegularOutput",
      "maxTries": 2,
      "position": [
        1600,
        216
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3.1-flash-lite-preview",
          "cachedResultName": "models/gemini-3.1-flash-lite-preview"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "={{ $json.prompt }}"
            }
          ]
        },
        "jsonOutput": true,
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "retryOnFail": true,
      "typeVersion": 1.1
    },
    {
      "id": "c663cc72-ea0f-48b7-853e-2b3268b4e2c2",
      "name": "Parse AI JSON Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1152,
        -144
      ],
      "parameters": {
        "jsCode": "const out = [];\n\nfor (const item of $input.all()) {\n  let text = item.json.content.parts[0].text;\n\n  text = text.replace(/```json/g, \"\").replace(/```/g, \"\").trim();\n\n  try {\n    const parsed = JSON.parse(text);\n    out.push({ json: parsed });\n  } catch (err) {\n    out.push({ json: { error: true, raw: text } });\n  }\n}\n\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "b994873e-48a0-4060-9b71-8c2e54fb888c",
      "name": "Calculate Impact Score",
      "type": "n8n-nodes-base.code",
      "position": [
        1376,
        -144
      ],
      "parameters": {
        "jsCode": "const output = [];\n\nfor (const item of $input.all()) {\n  const data = item.json;\n\n  let impact = 0;\n\n  if (data.sentiment === \"bullish\") impact = data.confidence * 1.2;\n  if (data.sentiment === \"bearish\") impact = data.confidence * -1.2;\n  if (data.sentiment === \"neutral\") impact = data.confidence * 0.3;\n\n  output.push({\n    json: {\n      ...data,\n      impact_score: Math.round(impact)\n    }\n  });\n}\n\nreturn output;"
      },
      "typeVersion": 2
    },
    {
      "id": "f72459a4-956d-4b77-baaf-7db46cbb89fc",
      "name": "Check High Impact News",
      "type": "n8n-nodes-base.if",
      "position": [
        1664,
        -240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "92d7bb28-0aee-4199-862c-37486f673491",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.impact_score }}",
              "rightValue": 60
            },
            {
              "id": "58bfbfdb-8c78-4d8a-877f-dd9674b6ec17",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.impact_score }}",
              "rightValue": -60
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "6b30785f-2d6d-4b30-be19-0b615aa77f59",
      "name": "Send Email Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1952,
        -240
      ],
      "parameters": {
        "sendTo": "",
        "message": "=Stock: {{$json.stock}} \nTitle: {{$json.title}}  \nSentiment: {{$json.sentiment}} \nImpact: {{$json.impact_score}}  \nReason: {{$json.reason}}",
        "options": {},
        "subject": "HIGH IMPACT NEWS",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5776ca7b-8652-43d4-9db2-6eb31d701182",
      "name": "Store Results in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1664,
        -48
      ],
      "parameters": {
        "columns": {
          "value": {
            "Stock": "={{ $json.stock }}",
            "Title": "={{ $json.title }}",
            "Reason": "={{ $json.reason }}",
            "Sentiment": "={{ $json.sentiment }}"
          },
          "schema": [
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Stock",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Stock",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sentiment",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Sentiment",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reason",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Titlle"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 583977364,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit#gid=583977364",
          "cachedResultName": "Stock news Sentiment"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit?usp=drivesdk",
          "cachedResultName": "N8N - PRACTICE"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "bdaec70e-d1a3-405b-ba86-ecc9e50cec88",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -248,
        -64
      ],
      "parameters": {
        "color": "#D6D6D6",
        "width": 432,
        "height": 368,
        "content": "### TRIGGER & FETCH NEWS\n\u2022 Runs daily at 8 AM  \n\u2022 Calls external Market News API  \n\u2022 Acts as workflow entry point  "
      },
      "typeVersion": 1
    },
    {
      "id": "0edfe3a6-9211-49fa-ad3b-bb2b64a16bea",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        200,
        -64
      ],
      "parameters": {
        "color": "#D6D6D6",
        "width": 656,
        "height": 368,
        "content": "### DATA CLEANING & DEDUPLICATION\n\u2022 Extracts latest news articles  \n\u2022 Limits number of items (top N)  \n\u2022 Standardizes structure:\n  - Title\n  - Content\n  - Stock name  \n\u2022 Removes duplicate news using title "
      },
      "typeVersion": 1
    },
    {
      "id": "78f6de84-7ecd-413c-925f-9f8255c568ef",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        896,
        48
      ],
      "parameters": {
        "color": "#D6D6D6",
        "width": 400,
        "height": 480,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n### ITERATION & RATE CONTROL\n\u2022 Processes news one-by-one  \n\u2022 Uses batching to control flow  \n\u2022 Adds delay (Wait node) to avoid API limits  "
      },
      "typeVersion": 1
    },
    {
      "id": "1c814084-633c-4b63-ae7e-cd36dc78bc3d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1328,
        112
      ],
      "parameters": {
        "color": "#D6D6D6",
        "width": 544,
        "height": 448,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n### AI SENTIMENT ANALYSIS\n\u2022 Builds structured prompt for Gemini  \n\u2022 Sends title + content for analysis  \n\u2022 Returns JSON with:\n  - Sentiment (bullish/bearish/neutral)\n  - Confidence score\n  - Reason  "
      },
      "typeVersion": 1
    },
    {
      "id": "588244e2-1732-49a6-adfc-761eff8b6623",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1088,
        -384
      ],
      "parameters": {
        "color": "#D6D6D6",
        "width": 448,
        "height": 400,
        "content": "### OUTPUT PARSING AND  IMPACT SCORING\n\u2022 Cleans Gemini response    \n\u2022 Converts text to valid JSON    \n\u2022 Calculates impact score using:\n  - Sentiment\n  - Confidence "
      },
      "typeVersion": 1
    },
    {
      "id": "20d68cdb-2dec-4c38-8ab1-6fdd30e2ad4d",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1592,
        -432
      ],
      "parameters": {
        "color": "#D6D6D6",
        "width": 528,
        "height": 528,
        "content": "### HIGH IMPACT FILTER,  ALERT SYSTEM (EMAIL) AND DATA STORAGE (GOOGLE SHEETS)\n\n\u2022 Filters strong signals using thresholds    \n\u2022 Sends email for high-impact news  \n\u2022 Appends results to sheet  "
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Send Email Alert": {
      "main": [
        []
      ]
    },
    "AI Sentiment Analysis": {
      "main": [
        [
          {
            "node": "Process News One-by-One",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Market News API": {
      "main": [
        [
          {
            "node": "Select Top News Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize News Fields": {
      "main": [
        [
          {
            "node": "Remove Duplicate News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicate News": {
      "main": [
        [
          {
            "node": "Process News One-by-One",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Throttle / Rate Limit": {
      "main": [
        [
          {
            "node": "Generate Sentiment Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Impact Score": {
      "main": [
        [
          {
            "node": "Check High Impact News",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store Results in Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check High Impact News": {
      "main": [
        [
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily 8AM News Trigger": {
      "main": [
        [
          {
            "node": "Fetch Market News API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI JSON Response": {
      "main": [
        [
          {
            "node": "Calculate Impact Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process News One-by-One": {
      "main": [
        [
          {
            "node": "Parse AI JSON Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Throttle / Rate Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Top News Articles": {
      "main": [
        [
          {
            "node": "Normalize News Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Sentiment Prompt": {
      "main": [
        [
          {
            "node": "AI Sentiment Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}