{
  "id": "UeiBg6dNaaXiBihb",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Turn Financial Statements and News into Weekly AI Equity Research Reports",
  "tags": [],
  "nodes": [
    {
      "id": "8ba91d18-01b8-426f-a48f-cd431ebd5ec7",
      "name": "Weekly Equity Research Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -96,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "3c5ba0e3-ee70-4a08-9022-368dc51ef413",
      "name": "Fetch Company List",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        112,
        0
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1378200588,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Mz-woYDtXtzF2bA9IqpdYh28IPA76nFx46WHgDJOZoI/edit#gid=1378200588",
          "cachedResultName": "companies"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Mz-woYDtXtzF2bA9IqpdYh28IPA76nFx46WHgDJOZoI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Mz-woYDtXtzF2bA9IqpdYh28IPA76nFx46WHgDJOZoI/edit?usp=drivesdk",
          "cachedResultName": "NEWS IMPACT TRACKER"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "1628fc88-b809-4ac3-a5c4-eb7a8dfaca42",
      "name": "Fetch Income Statement",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1072,
        -224
      ],
      "parameters": {
        "url": "=https://financialmodelingprep.com/stable/income-statement",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "period",
              "value": "annual"
            },
            {
              "name": "limit",
              "value": "5"
            },
            {
              "name": "apikey",
              "value": "your_api_key"
            },
            {
              "name": "symbol",
              "value": "={{ $json.ticker }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "4a3bd331-1c82-47f4-aa48-e2a44e37e8bd",
      "name": "Fetch Balance Sheet",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1056,
        -16
      ],
      "parameters": {
        "url": "=https://financialmodelingprep.com/stable/balance-sheet-statement",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "period",
              "value": "annual"
            },
            {
              "name": "limit",
              "value": "5"
            },
            {
              "name": "apikey",
              "value": "your_api_key"
            },
            {
              "name": "symbol",
              "value": "={{ $json.ticker }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "cc3dd95e-cec9-4326-99ee-e118f6efe1ae",
      "name": "Fetch Cash Flow",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1040,
        208
      ],
      "parameters": {
        "url": "=https://financialmodelingprep.com/stable/cash-flow-statement",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "period",
              "value": "annual"
            },
            {
              "name": "limit",
              "value": "5"
            },
            {
              "name": "apikey",
              "value": "your_api_key"
            },
            {
              "name": "symbol",
              "value": "={{ $json.ticker }}"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "8713c97c-84e1-4fa1-ae93-8e2f674a0649",
      "name": "Fetch Market Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1040,
        448
      ],
      "parameters": {
        "url": "https://newsapi.org/v2/everything",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $json.ticker }}"
            },
            {
              "name": "language",
              "value": "=en"
            },
            {
              "name": "sortBy",
              "value": "publishedAt"
            },
            {
              "name": "pageSize",
              "value": "10"
            },
            {
              "name": "apiKey",
              "value": "your_newsapi_key"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "d7ebfa69-69d7-4543-93c4-8132a34b555f",
      "name": "Parse Risks and Growth Output",
      "type": "n8n-nodes-base.code",
      "position": [
        2672,
        224
      ],
      "parameters": {
        "jsCode": "let raw = $json.output;\nlet parsed = {};\n\ntry {\n  parsed = JSON.parse(raw);\n} catch (e) {\n  parsed = {\n    risks: [],\n    growth_outlook: \"\"\n  };\n}\n\nreturn [\n  {\n    json: parsed\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d9606f85-e284-4a04-896e-e1877d778854",
      "name": "Build Equity Research Report",
      "type": "n8n-nodes-base.code",
      "position": [
        3248,
        96
      ],
      "parameters": {
        "jsCode": "const {\n  strengths = [],\n  weaknesses = [],\n  opportunities = [],\n  threats = [],\n  risks = [],\n  growth_outlook = \"\"\n} = $json;\n\n// Helper to render bullet lists\nconst renderList = (items) =>\n  items.map(item => `<li>${item}</li>`).join(\"\");\n\n// Build HTML report\nconst html = `\n<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\" />\n  <style>\n    body {\n      font-family: Arial, sans-serif;\n      line-height: 1.6;\n      color: #222;\n      padding: 24px;\n    }\n    h1 {\n      color: #0b5ed7;\n      border-bottom: 2px solid #eee;\n      padding-bottom: 8px;\n    }\n    h2 {\n      color: #333;\n      margin-top: 24px;\n    }\n    ul {\n      margin-left: 20px;\n    }\n    li {\n      margin-bottom: 6px;\n    }\n    .section {\n      margin-bottom: 24px;\n    }\n  </style>\n</head>\n<body>\n\n<h1>AI-Generated Equity Research Report</h1>\n\n<div class=\"company\">\n<h2> Symbol : </h2><span>${ $('Iterate Companies').item.json.ticker }</span>\n</div>\n\n<div class=\"section\">\n  <h2>Strengths</h2>\n  <ul>${renderList(strengths)}</ul>\n</div>\n\n<div class=\"section\">\n  <h2>Weaknesses</h2>\n  <ul>${renderList(weaknesses)}</ul>\n</div>\n\n<div class=\"section\">\n  <h2>Opportunities</h2>\n  <ul>${renderList(opportunities)}</ul>\n</div>\n\n<div class=\"section\">\n  <h2>Threats</h2>\n  <ul>${renderList(threats)}</ul>\n</div>\n\n<div class=\"section\">\n  <h2>Key Risks</h2>\n  <ul>${renderList(risks)}</ul>\n</div>\n\n<div class=\"section\">\n  <h2>Growth Outlook (12\u201324 Months)</h2>\n  <p>${growth_outlook}</p>\n</div>\n\n</body>\n</html>\n`;\n\nreturn [\n  {\n    json: {\n      report_html: html\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8fe6ee7c-1af0-44d5-9c9d-c1d166a7149c",
      "name": "Filter Enabled Companies",
      "type": "n8n-nodes-base.if",
      "position": [
        320,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8c7418be-b1e2-41bc-8850-f3b25b9665db",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.enabled }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "7c0d21eb-d7d3-4627-984a-34298c5a1d22",
      "name": "Iterate Companies",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        576,
        -16
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "c336316a-32f2-4dce-ac59-3bbe7543aabf",
      "name": "Normalize Income Statement Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        -224
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst normalized = items.slice(0, 5).map(item => {\n  const s = item.json;\n  return {\n    fiscal_year: s.fiscalYear,\n    revenue: s.revenue,\n    gross_profit: s.grossProfit,\n    operating_income: s.operatingIncome,\n    ebitda: s.ebitda,\n    net_income: s.netIncome,\n    eps_diluted: s.epsDiluted\n  };\n});\n\nreturn [\n  {\n    json: {\n      income_statement: normalized\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "96fd276d-882f-4977-be51-7f5bfc72d4e7",
      "name": "Normalize Balance Sheet Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1296,
        -16
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst normalized = items.slice(0, 5).map(item => {\n  const s = item.json;\n  return {\n    fiscal_year: s.fiscalYear,\n    assets: {\n      cash_and_equivalents: s.cashAndCashEquivalents,\n      total_current_assets: s.totalCurrentAssets,\n      total_assets: s.totalAssets\n    },\n    liabilities: {\n      total_current_liabilities: s.totalCurrentLiabilities,\n      short_term_debt: s.shortTermDebt,\n      long_term_debt: s.longTermDebt,\n      total_liabilities: s.totalLiabilities\n    },\n    debt: {\n      total_debt: s.totalDebt,\n      net_debt: s.netDebt\n    },\n    equity: {\n      total_equity: s.totalEquity\n    }\n  };\n});\n\nreturn [\n  {\n    json: {\n      balance_sheet: normalized\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "7473b880-a93d-4fcd-a41c-b3ce0d52d113",
      "name": "Normalize Cash Flow Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        208
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst normalized = items.slice(0, 5).map(item => {\n  const s = item.json;\n  return {\n    fiscal_year: s.fiscalYear,\n    cash_generation: {\n      operating_cash_flow: s.operatingCashFlow,\n      free_cash_flow: s.freeCashFlow,\n      capital_expenditure: s.capitalExpenditure\n    },\n    earnings_to_cash: {\n      net_income: s.netIncome,\n      depreciation_and_amortization: s.depreciationAndAmortization,\n      change_in_working_capital: s.changeInWorkingCapital\n    },\n    capital_allocation: {\n      dividends_paid: s.netDividendsPaid,\n      stock_repurchased: s.commonStockRepurchased,\n      net_debt_issuance: s.netDebtIssuance\n    }\n  };\n});\n\nreturn [\n  {\n    json: {\n      cash_flow: normalized\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5c365c91-e0c8-4268-bb17-edbcc6d98640",
      "name": "Normalize Market News Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        448
      ],
      "parameters": {
        "jsCode": "// NewsAPI response structure: { status, totalResults, articles }\nconst articles = $json.articles || [];\n\n// Normalize and limit articles\nconst normalized = articles.slice(0, 5).map(a => ({\n  title: a.title,\n  summary: a.description,\n  source: a.source?.name || null,\n  published_at: a.publishedAt,\n  url: a.url\n}));\n\nreturn {\n  news: normalized\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "1b2300e2-164a-41ed-8702-b6746d4e2ad5",
      "name": "Merge Financials and News",
      "type": "n8n-nodes-base.merge",
      "position": [
        1808,
        64
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition",
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "ef44be38-7acb-4e8b-a3a9-2b8bb5350ff4",
      "name": "Compute Financial and Market Signals",
      "type": "n8n-nodes-base.code",
      "position": [
        2016,
        96
      ],
      "parameters": {
        "jsCode": "const data = $json;\n\nconst income = data.income_statement;\nconst balance = data.balance_sheet;\nconst cash = data.cash_flow;\n\n// Latest vs oldest for trends\nconst latestIncome = income[0];\nconst oldestIncome = income[income.length - 1];\n\nconst revenueGrowth =\n  (latestIncome.revenue - oldestIncome.revenue) / oldestIncome.revenue;\n\nconst margin =\n  latestIncome.operating_income / latestIncome.revenue;\n\nconst latestBalance = balance[0];\nconst debtToEquity =\n  latestBalance.debt.total_debt / latestBalance.equity.total_equity;\n\nconst latestCash = cash[0];\nconst fcfMargin =\n  latestCash.cash_generation.free_cash_flow / latestIncome.revenue;\n\nreturn {\n  swot_signals: {\n    revenue_growth_5y: revenueGrowth,\n    operating_margin: margin,\n    debt_to_equity: debtToEquity,\n    fcf_margin: fcfMargin,\n    stock_buybacks: latestCash.capital_allocation.stock_repurchased,\n    news : data.news,\n    news_count: data.news.length\n  },\n  original_data: data\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ed0d6bf4-3b0e-4efc-ac24-b3db27bd118f",
      "name": "LLM \u2013 SWOT Analysis Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2304,
        48
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "e6bc944b-fbc4-4cc8-8997-53bbc8cf0086",
      "name": "Generate SWOT Analysis",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2304,
        -128
      ],
      "parameters": {
        "text": "=You are an equity research analyst.\n\nInput :  {{ $json.toJsonString() }}\n\nInput contains:\n- Quantitative SWOT signals\n- Clean financial statements\n- Recent news headlines\n\nRules:\n- Use the signals to determine SWOT categories\n- Do NOT invent data\n- Base each point on either:\n  (a) a numeric signal\n  (b) a news item\n- Be concise and factual\n\nReturn ONLY valid JSON in this format:\n\n{\n  \"strengths\": [],\n  \"weaknesses\": [],\n  \"opportunities\": [],\n  \"threats\": []\n}\n",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "f17c2007-0500-4b81-ad6e-28ce901ccb14",
      "name": "Parse SWOT Output",
      "type": "n8n-nodes-base.code",
      "position": [
        2672,
        -128
      ],
      "parameters": {
        "jsCode": "let raw = $json.output;\nlet parsed = {};\n\ntry {\n  parsed = JSON.parse(raw);\n} catch (e) {\n  parsed = {\n    strengths: [],\n    weaknesses: [],\n    opportunities: [],\n    threats: []\n  };\n}\n\nreturn [\n  {\n    json: parsed\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "afe5d9bd-8a0f-412c-996a-b9b8ada81223",
      "name": "LLM \u2013 Risk and Growth Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2320,
        400
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "0b183d35-b6ad-4dc4-8ad5-b936f716c1da",
      "name": "Generate Risks and Growth Outlook",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2320,
        224
      ],
      "parameters": {
        "text": "=You are an equity research analyst.\n\nSwot signals : {{ $json.swot_signals.toJsonString() }}\n\noriginal_data : {{ $json.original_data.toJsonString() }}\n\nInput contains:\n- Calculated financial signals under \"swot_signals\"\n- Full normalized financial and news data under \"original_data\"\n\nTasks:\n1. Identify key business and financial risks\n2. Provide a 12\u201324 month growth outlook\n\nRules:\n- Base analysis on the provided data only\n- Use signals where applicable (leverage, margins, cash flow)\n- Do not invent facts\n\nReturn ONLY valid JSON in this format:\n\n{\n  \"risks\": [],\n  \"growth_outlook\": \"\"\n}\n",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "06fd7960-2806-4c4f-b595-f52fa79977d8",
      "name": "Merge All AI Insights",
      "type": "n8n-nodes-base.merge",
      "position": [
        2992,
        96
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "44902b8c-483f-44fd-83ac-a9ee67b7e0f7",
      "name": "Render Research Report to PDF",
      "type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
      "position": [
        3520,
        96
      ],
      "parameters": {
        "html_content": "={{ $json.report_html }}"
      },
      "credentials": {
        "htmlcsstopdfApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c3f4e60c-9786-4153-9c41-c8519dab017b",
      "name": "Validate PDF Generation",
      "type": "n8n-nodes-base.if",
      "position": [
        3728,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8e7309e6-ef35-4ff5-abde-a1ee86f100aa",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.success }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "110a466a-abd8-4b4e-a69b-1b9c651effc8",
      "name": "Log Report Metadata",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4096,
        -48
      ],
      "parameters": {
        "columns": {
          "value": {
            "Company": "={{ $('Iterate Companies').item.json.ticker }}",
            "PDF URL": "={{$json.pdf_url}}",
            "Timestamp": "={{$now}}",
            "Expiry Date": "={{$json.file_deletion_date}}",
            "Report Type": "AI Equity Research",
            "File Size (KB)": "={{ Math.round($json.file_size_bytes / 1024) }}"
          },
          "schema": [
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Company",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Report Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Report Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "File Size (KB)",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "File Size (KB)",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "PDF URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "PDF URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Expiry Date",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Expiry Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1571135394,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Mz-woYDtXtzF2bA9IqpdYh28IPA76nFx46WHgDJOZoI/edit#gid=1571135394",
          "cachedResultName": "AI Equity Research Report"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Mz-woYDtXtzF2bA9IqpdYh28IPA76nFx46WHgDJOZoI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Mz-woYDtXtzF2bA9IqpdYh28IPA76nFx46WHgDJOZoI/edit?usp=drivesdk",
          "cachedResultName": "NEWS IMPACT TRACKER"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e90a99b4-3609-4d8d-8a69-186d1b011adb",
      "name": "Send Email Equity Research Report",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4080,
        224
      ],
      "parameters": {
        "sendTo": "your_email_id",
        "message": "=<p>Hello,</p>  <p>Your <strong>AI-generated Equity Research Report</strong> has been successfully generated.</p>  <p> <strong>Download PDF:</strong><br/> <a href=\"{{ $json.pdf_url }}\" target=\"_blank\"> View / Download Report </a> </p>  <p> <strong>File size:</strong> {{ Math.round($json.file_size_bytes / 1024) }} KB<br/> <strong>Link valid until:</strong> {{ $json.file_deletion_date }} </p>  <p> Regards,<br/> AI Equity Research Automation </p>",
        "options": {
          "appendAttribution": false
        },
        "subject": "AI Equity Research Report \u2013 Ready for Review"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a295329e-3444-43d4-8e71-9d640d2724e1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -1072
      ],
      "parameters": {
        "width": 512,
        "height": 752,
        "content": "## Workflow Overview \n\n### How it works\n\nThis workflow automatically creates a professional equity research report for selected companies on a weekly basis. It begins by reading a list of companies from Google Sheets and checks which ones are enabled for analysis. Only enabled companies are processed, making it easy to control coverage without changing the workflow.\n\nFor each company, the workflow collects five years of financial data, including income statement, balance sheet, and cash flow information, from Financial Modeling Prep. At the same time, it pulls recent market-related news using NewsAPI. All raw data is cleaned and normalized so it follows a consistent and easy-to-analyze structure.\n\nOnce the data is prepared, key financial signals such as revenue growth, operating margins, free cash flow strength, and leverage ratios are calculated. These signals, along with recent news, are passed to AI models that generate a structured SWOT analysis, identify major risks, and provide a 12\u201324 month growth outlook. The AI is strictly guided to base its output only on the provided data.\n\nThe generated insights are compiled into a clean HTML equity research report, which is then converted into a PDF. If the PDF is created successfully, the workflow logs the report details in Google Sheets and sends an email containing the PDF download link.\n\n### Setup steps:\n\nAdd company tickers and an enabled column in Google Sheets\n\nConfigure Financial Modeling Prep, NewsAPI, and OpenAI API keys\n\nConnect Google Sheets and Gmail credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "2c6bb56b-b7c6-4586-9361-553bed73afdd",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 416,
        "content": "### Company Selection and Looping\n\nThese nodes load companies from Google Sheets, filters only enabled entries, and loops through each company one at a time. It ensures controlled execution and allows users to manage company coverage directly from the sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "57eaaf05-32fc-453e-90fb-2f041e9b482f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 816,
        "height": 1024,
        "content": "### Financial and News Data Collection\n\nThese nodes fetch financial statements and recent market news from external APIs. Keeping data collection separate helps maintain clarity, simplifies troubleshooting, and ensures reliable inputs for later normalization and analysis steps."
      },
      "typeVersion": 1
    },
    {
      "id": "b3e5364a-f0db-4b26-a0d4-0b1e3dc7041e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1728,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 1408,
        "height": 1024,
        "content": "### AI Analysis and Signal Generation\n\nThis group calculates financial signals and uses AI to generate SWOT insights, risks, and growth outlook. The AI relies only on computed metrics and recent news, avoiding assumptions or unsupported conclusions."
      },
      "typeVersion": 1
    },
    {
      "id": "47343c7f-5a6b-47fb-bdae-0dfaf6844ad6",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3200,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 1200,
        "height": 560,
        "content": "### Report Generation and Delivery \n\nThese nodes assemble the final report, convert it into a PDF, log key details in Google Sheets, and send the report link by email once generation is confirmed successful."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "cf197bd4-d253-4ffc-a8f7-827eed52ab7c",
  "connections": {
    "Fetch Cash Flow": {
      "main": [
        [
          {
            "node": "Normalize Cash Flow Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Market Data": {
      "main": [
        [
          {
            "node": "Normalize Market News Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Iterate Companies": {
      "main": [
        [],
        [
          {
            "node": "Fetch Income Statement",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Balance Sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Cash Flow",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Market Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse SWOT Output": {
      "main": [
        [
          {
            "node": "Merge All AI Insights",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Company List": {
      "main": [
        [
          {
            "node": "Filter Enabled Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Balance Sheet": {
      "main": [
        [
          {
            "node": "Normalize Balance Sheet Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All AI Insights": {
      "main": [
        [
          {
            "node": "Build Equity Research Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Income Statement": {
      "main": [
        [
          {
            "node": "Normalize Income Statement Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate SWOT Analysis": {
      "main": [
        [
          {
            "node": "Parse SWOT Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate PDF Generation": {
      "main": [
        [
          {
            "node": "Log Report Metadata",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Email Equity Research Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Enabled Companies": {
      "main": [
        [
          {
            "node": "Iterate Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Cash Flow Data": {
      "main": [
        [
          {
            "node": "Merge Financials and News",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Merge Financials and News": {
      "main": [
        [
          {
            "node": "Compute Financial and Market Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Market News Data": {
      "main": [
        [
          {
            "node": "Merge Financials and News",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "LLM \u2013 SWOT Analysis Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate SWOT Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Build Equity Research Report": {
      "main": [
        [
          {
            "node": "Render Research Report to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Balance Sheet Data": {
      "main": [
        [
          {
            "node": "Merge Financials and News",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "LLM \u2013 Risk and Growth Model": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Risks and Growth Outlook",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse Risks and Growth Output": {
      "main": [
        [
          {
            "node": "Merge All AI Insights",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Render Research Report to PDF": {
      "main": [
        [
          {
            "node": "Validate PDF Generation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Equity Research Trigger": {
      "main": [
        [
          {
            "node": "Fetch Company List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Income Statement Data": {
      "main": [
        [
          {
            "node": "Merge Financials and News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Risks and Growth Outlook": {
      "main": [
        [
          {
            "node": "Parse Risks and Growth Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Equity Research Report": {
      "main": [
        [
          {
            "node": "Iterate Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compute Financial and Market Signals": {
      "main": [
        [
          {
            "node": "Generate SWOT Analysis",
            "type": "main",
            "index": 0
          },
          {
            "node": "Generate Risks and Growth Outlook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}