{
  "id": "aaHxbEv62l7f9mlA",
  "name": "AI-Powered Financial Market Alert System",
  "tags": [],
  "nodes": [
    {
      "id": "9491205a-bf91-4a98-8437-098eda703848",
      "name": "AI Event Classification Node",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1504,
        592
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=You are an AI financial market event classifier.\n\nAnalyze the provided stock market news and return ONLY valid JSON.\n\nYour task:\n\n1. Identify the event type\n2. Determine impact severity\n3. Detect whether alert should be sent\n4. Estimate short-term market impact\n5. Classify investor relevance\n\nSeverity Rules:\n- Low \u2192 routine updates\n- Medium \u2192 moderate business impact\n- High \u2192 important operational/business event\n- Critical \u2192 major market-moving event\nDo NOT send alerts for:\n- Board meetings\n- Earnings schedules\n- Investor calls\n- Newspaper publication notices\n- Routine compliance filings\n\nOnly send alerts if real business impact exists.\n\nHigh/Critical examples:\n- Large contracts\n- Government approvals\n- Regulatory actions\n- Strategic partnerships\n- Major acquisitions\n- Fraud/compliance issues\n- Production expansion\n- Significant investments\n\nIgnore/Low examples:\n- Board meetings\n- Earnings call schedules\n- Routine filings\n- Conference announcements\n\nReturn JSON in this exact structure:\n\n{\n  \"event_type\": \"\",\n  \"severity\": \"\",\n  \"send_alert\": true,\n  \"market_impact\": \"\",\n  \"investor_relevance\": \"\",\n  \"summary\": \"\"\n}\n\nNews Title:\n{{$json.title}}\n\nNews Description:\n{{$json.description}}\n\nCompany:\n{{$json.stock_name}}\n\nSector:\n{{$json.sector}}\n\nMarket Cap:\n{{$json.market_cap}}\n\nSentiment:\n{{$json.sentiment}}"
            }
          ]
        },
        "builtInTools": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "696d900a-903e-43af-958b-9e93a70a752a",
      "name": "Daily Market News Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        768,
        592
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 10
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "dda7e25f-f6fe-41ee-9ed2-fef45e52fbae",
      "name": "Fetch Market News API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        960,
        592
      ],
      "parameters": {
        "url": "https://api.tradient.org/v1/api/market/news  ",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "19f9032c-96e9-4590-8706-14b5a66d2d7b",
      "name": "Filter & Normalize News",
      "type": "n8n-nodes-base.code",
      "position": [
        1184,
        592
      ],
      "parameters": {
        "jsCode": "// ===== MARKET HOURS FILTER =====\n\nconst now = new Date();\n\nconst istTime = new Date(\n  now.toLocaleString(\"en-US\", {\n    timeZone: \"Asia/Kolkata\"\n  })\n);\n\nconst hour = istTime.getHours();\nconst minutes = istTime.getMinutes();\n\n// NSE/BSE: 9:15 AM \u2192 3:30 PM\n\nconst isMarketOpen =\n(\n  (hour > 9 || (hour === 9 && minutes >= 15))\n  &&\n  (hour < 15 || (hour === 15 && minutes <= 30))\n);\n\nif (!isMarketOpen) {\n\n  console.log(\"Market Closed\");\n\n  return [];\n}\n\n// ===== FETCH NEWS =====\n\nconst news = $json.data.latest_news || [];\n\n// Important categories\n\nconst importantSubCategories = [\n  \"operational-updates\",\n  \"strategic-partnerships\",\n  \"legal-compliance\",\n  \"product-launches-innovation\",\n  \"management-leadership\"\n];\n\n// Important keywords\n\nconst importantKeywords = [\n  \"contract\",\n  \"order\",\n  \"partnership\",\n  \"acquisition\",\n  \"merger\",\n  \"expansion\",\n  \"investment\",\n  \"government\",\n  \"approval\",\n  \"launch\",\n  \"compliance\",\n  \"fraud\",\n  \"penalty\",\n  \"warning\",\n  \"shutdown\",\n  \"capacity\",\n  \"deal\",\n  \"mou\",\n  \"growth\"\n];\n\n// Ignore boring news\n\nconst ignorePatterns = [\n  \"board meeting\",\n  \"earnings call\",\n  \"financial results\",\n  \"conference call\",\n  \"audited results\"\n];\n\nconst filteredNews = news\n.filter(item => {\n\n  const title =\n    item.news_object?.title?.toLowerCase() || \"\";\n\n  const text =\n    item.news_object?.text?.toLowerCase() || \"\";\n\n  const subCategory =\n    item.sub_category || \"\";\n\n  const importantCategory =\n    importantSubCategories.includes(subCategory);\n\n  const keywordMatch =\n    importantKeywords.some(keyword =>\n      title.includes(keyword) ||\n      text.includes(keyword)\n    );\n\n  const isIgnored =\n    ignorePatterns.some(pattern =>\n      title.includes(pattern) ||\n      text.includes(pattern)\n    );\n\n  return (importantCategory || keywordMatch) && !isIgnored;\n})\n\n.map(item => {\n\n  return {\n    json: {\n\n      title:\n        item.news_object?.title || \"\",\n\n      description:\n        item.news_object?.text || \"\",\n\n      short_description:\n        (item.news_object?.text || \"\").slice(0, 250),\n\n      sentiment:\n        item.news_object?.overall_sentiment || \"neutral\",\n\n      category:\n        item.category || \"\",\n\n      sub_category:\n        item.sub_category || \"\",\n\n      stock_name:\n        item.stock_name || \"\",\n\n      symbol:\n        item.sm_symbol || \"\",\n\n      market_cap:\n        item.metadata?.marketcap || \"\",\n\n      sector:\n        item.metadata?.sector_name || \"\",\n\n      publish_date:\n        item.publish_date || \"\",\n\n      article_id:\n        item.article_id || \"\",\n\n      article_slug:\n        item.article_slug || \"\",\n\n      impact_score:\n        item.news_object?.overall_sentiment === \"positive\"\n          ? 8\n          : item.news_object?.overall_sentiment === \"negative\"\n          ? 7\n          : 5\n    }\n  };\n});\n\nreturn filteredNews;"
      },
      "typeVersion": 2
    },
    {
      "id": "ea71e3ab-a3a1-40ad-83b5-93e9d1144719",
      "name": "Parse AI Classification JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        1840,
        592
      ],
      "parameters": {
        "jsCode": "const rawText =\n  $json.content?.[0]?.text || \"\";\n\nlet parsed;\n\ntry {\n\n  parsed = JSON.parse(rawText);\n\n} catch (error) {\n\n  parsed = {\n    event_type: \"Unknown\",\n    severity: \"Low\",\n    send_alert: false,\n    market_impact: \"\",\n    investor_relevance: \"\",\n    summary: \"\"\n  };\n}\n\nreturn [\n  {\n    json: {\n      ...$input.item.json,\n      ...parsed\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "a955e527-b319-4132-8038-6a0c9e233e99",
      "name": "Check Important Market Event",
      "type": "n8n-nodes-base.if",
      "position": [
        2032,
        592
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c687a8ee-07a2-4eaf-b4ee-c069988d2802",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{$json.send_alert}}",
              "rightValue": "true"
            },
            {
              "id": "1c44479b-04de-49e5-afea-bec8c818a270",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{$json.severity}}",
              "rightValue": "Low"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3,
      "alwaysOutputData": false
    },
    {
      "id": "663677ea-ffaa-44b1-bfed-698ad80678e8",
      "name": "Remove Duplicate Articles",
      "type": "n8n-nodes-base.code",
      "position": [
        2272,
        576
      ],
      "parameters": {
        "jsCode": "const seen = new Set();\n\nreturn items.filter(item => {\n\n  const id =\n    item.json.article_id;\n\n  if (seen.has(id)) {\n    return false;\n  }\n\n  seen.add(id);\n\n  return true;\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "255cafb2-60f7-490b-8f5f-bf2e04402d4f",
      "name": "Parse Investor Alert JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        2832,
        560
      ],
      "parameters": {
        "jsCode": "const rawText = $json.content[0].text;\n\nlet parsed;\n\ntry {\n  parsed = JSON.parse(rawText);\n} catch (e) {\n\n  parsed = {\n    headline: \"\",\n    alert_message: \"\",\n    sentiment: \"\",\n    priority: \"\"\n  };\n}\nif (\n  parsed.priority === \"\"\n) {\n\n  if (\n    $json.severity === \"Critical\"\n  ) {\n    parsed.priority = \"P1\";\n  }\n\n  else if (\n    $json.severity === \"High\"\n  ) {\n    parsed.priority = \"P2\";\n  }\n\n  else {\n    parsed.priority = \"P3\";\n  }\n}\n\n\nreturn [\n  {\n    json: {\n      ...$input.item.json,\n      ...parsed\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "fadfb1b2-1705-4ce5-bc28-aad1f865a853",
      "name": "Format Email Alert Data",
      "type": "n8n-nodes-base.set",
      "position": [
        3024,
        560
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3c0d8d5d-7dc8-462d-97cc-4b2919d33c86",
              "name": "Subject:",
              "type": "string",
              "value": "={{$json.priority}} Alert - {{$json.headline}}"
            },
            {
              "id": "960da2c0-00e1-4002-b94b-c27e626752f0",
              "name": "Company:",
              "type": "string",
              "value": "={{$json.stock_name}}"
            },
            {
              "id": "8a371c60-011d-44df-8f8d-c93a28342e79",
              "name": "Headline:",
              "type": "string",
              "value": "={{$json.headline}}"
            },
            {
              "id": "3e4ca6fc-b07b-4777-bc88-f8b822a96750",
              "name": "Alert:",
              "type": "string",
              "value": "={{$json.alert_message}}"
            },
            {
              "id": "bd235fd1-456d-4e01-8e94-4a8336d7d1e6",
              "name": "Sector:",
              "type": "string",
              "value": "={{$json.sector}}"
            },
            {
              "id": "1bc36d89-7870-4922-b6bd-996eae37f30b",
              "name": "Sentiment:",
              "type": "string",
              "value": "={{$json.sentiment}}"
            },
            {
              "id": "24539fc7-3452-4985-bc69-69262457bc65",
              "name": "Severity:",
              "type": "string",
              "value": "={{$json.severity}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fa2187fe-e19e-4b22-945a-37649653d1aa",
      "name": "Send Investor Email Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3248,
        560
      ],
      "parameters": {
        "message": "=<h2>{{$json.headline}}</h2>  <p>{{$json.alert_message}}</p>  <hr>  <ul> <li><b>Company:</b> {{$json.stock_name}}</li> <li><b>Sector:</b> {{$json.sector}}</li> <li><b>Severity:</b> {{$json.severity}}</li> <li><b>Sentiment:</b> {{$json.sentiment}}</li> </ul>",
        "options": {},
        "subject": "={{$json.Subject}}",
        "emailType": "text"
      },
      "typeVersion": 2.2
    },
    {
      "id": "74c633f7-4a11-455b-bd85-8dc7d895a0cf",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -144,
        0
      ],
      "parameters": {
        "width": 784,
        "height": 800,
        "content": "## AI-Powered Financial Market Alert System\n\nThis workflow automatically monitors live financial news and uses AI to detect high-impact market events. It filters irrelevant updates, classifies important business developments, removes duplicates, and sends concise investor alerts through email.\n\n### How It Works\n\n- Fetches latest market news from API\n- Filters low-value announcements\n- Detects important business events using keywords and categories\n- Uses AI to classify event severity and market impact\n- Validates whether alerts should be sent\n- Removes duplicate news articles\n- Generates concise investor alerts using AI\n- Formats and sends email notifications to investors\n\n### Setup Steps\n\n1. Daily Market News Trigger: Runs workflow automatically during market hours.\n2. Fetch Financial News: Retrieves latest stock market news from API.\n3. Filter & Normalize News: Cleans news data and removes irrelevant updates.\n4. AI Market Event Classification: AI analyzes severity, impact, and investor relevance.\n5. Validate Important Events: Allows only High/Critical impactful events.\n6. Remove Duplicate Articles: Prevents repeated investor alerts.\n7. Generate Investor Alert: AI creates concise professional alert messages.\n8. Format Email Alert: Prepares structured investor email content.\n9. Send Investor Email Alert: Sends final alerts through Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "612ccb0f-759e-4f00-8cea-e95ad4c87bbe",
      "name": "Generate Advisor Alert",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2528,
        560
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=You are an expert financial market advisor assistant.\n\nConvert the stock market event into a concise professional investor alert.\n\nGuidelines:\n- Keep it under 80 words\n- Focus on business impact\n- Mention whether sentiment is bullish, bearish, or neutral\n- Make it readable for traders and investors\n- Avoid hype\n- Be concise and actionable\n\nReturn ONLY valid JSON.\n\nFormat:\n\n{\n  \"headline\": \"\",\n  \"alert_message\": \"\",\n  \"sentiment\": \"\",\n  \"priority\": \"\"\n}\n\nEvent Type:\n{{$json.event_type}}\n\nSeverity:\n{{$json.severity}}\n\nSummary:\n{{$json.summary}}\n\nMarket Impact:\n{{$json.market_impact}}\n\nInvestor Relevance:\n{{$json.investor_relevance}}\n\nShort Description:\n{{$json.short_description}}\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "bc5a88a6-5375-4c4b-b33e-aae0ea240fc8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 608,
        "content": "###  News Ingestion & Market Validation\n\nThis section handles news collection and validates whether the workflow should run during active market hours.\n\nDaily Market News Trigger\nFetch Market News API\nFilter & Normalize News\nMarket Hours Validation"
      },
      "typeVersion": 1
    },
    {
      "id": "ee08e766-6ebd-44f4-a31a-8a258eccc307",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 976,
        "height": 608,
        "content": "###  AI Event Detection & Filtering\n\nThis section identifies impactful financial events using AI and business validation rules.\n\nAI Market Event Classifier\nParse AI Classification JSON\nCheck Important Market Event\nRemove Duplicate Articles"
      },
      "typeVersion": 1
    },
    {
      "id": "436a0775-1886-411d-9b07-003644ff4e7a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2464,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 944,
        "height": 608,
        "content": "###  Investor Alert Generation\n\nThis section generates concise investor alerts and formats them for delivery.\n\nGenerate Investor Alert\nParse Investor Alert JSON\nFormat Email Alert Data\nSend Investor Email Alert"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "b3b343eb-bb1b-4c97-be25-a32fdf82ebb5",
  "nodeGroups": [],
  "connections": {
    "Fetch Market News API": {
      "main": [
        [
          {
            "node": "Filter & Normalize News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Advisor Alert": {
      "main": [
        [
          {
            "node": "Parse Investor Alert JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter & Normalize News": {
      "main": [
        [
          {
            "node": "AI Event Classification Node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Email Alert Data": {
      "main": [
        [
          {
            "node": "Send Investor Email Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Market News Trigger": {
      "main": [
        [
          {
            "node": "Fetch Market News API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Investor Alert JSON": {
      "main": [
        [
          {
            "node": "Format Email Alert Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicate Articles": {
      "main": [
        [
          {
            "node": "Generate Advisor Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Event Classification Node": {
      "main": [
        [
          {
            "node": "Parse AI Classification JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Important Market Event": {
      "main": [
        [
          {
            "node": "Remove Duplicate Articles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Classification JSON": {
      "main": [
        [
          {
            "node": "Check Important Market Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}