AutomationFlowsAI & RAG › Send a Daily Investment Research Email with Olostep, Openai, and Gmail

Send a Daily Investment Research Email with Olostep, Openai, and Gmail

ByAbid Ali Awan @kingabzpro on n8n.io

This n8n template researches a stock watchlist with Olostep, turns the results into a concise OpenAI-generated investment research report, converts the report into a styled HTML email, and sends it with Gmail.

Cron / scheduled trigger★★★★☆ complexityAI-powered14 nodesN8N Nodes OlostepOpenAIGmail
AI & RAG Trigger: Cron / scheduled Nodes: 14 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #15387 — we link there as the canonical source.

This workflow follows the Gmail → OpenAI recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "My workflow",
  "tags": [],
  "nodes": [
    {
      "id": "7b8a7091-1a76-426e-a2ac-76eeb1277ca7",
      "name": "Weekday Market Open Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        2352,
        1024
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "30 9 * * 1-5"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ab3663e3-d555-4243-af04-b0f7395248eb",
      "name": "Manual Test Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        2352,
        1216
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ec693c8f-fd72-4626-9294-24934b575632",
      "name": "Investment Watchlist",
      "type": "n8n-nodes-base.set",
      "position": [
        2576,
        1120
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "name": "tickers",
              "type": "string",
              "value": "MSFT,NVDA"
            },
            {
              "name": "email_to",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "name": "email_from",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "name": "email_subject_prefix",
              "type": "string",
              "value": "Daily Investment Research Report"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5e7b3d45-94d2-4c80-8599-59866022e983",
      "name": "Split Tickers",
      "type": "n8n-nodes-base.code",
      "position": [
        2800,
        1120
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst tickers = data.tickers.split(',').map(function(t) { return t.trim(); }).filter(Boolean);\n\nreturn tickers.map(function(ticker) {\n  return {\n    json: {\n      ticker: ticker,\n      investment_query: ticker + ' latest investor relations SEC filings earnings call transcript financial news risk factors catalysts',\n      email_to: data.email_to,\n      email_from: data.email_from,\n      email_subject_prefix: data.email_subject_prefix\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "7d0aed34-9b35-494f-a62c-ad65bac5a1bb",
      "name": "Olostep Search - Investment Sources",
      "type": "n8n-nodes-olostep.olostepScrape",
      "position": [
        3024,
        1120
      ],
      "parameters": {
        "query": "={{ $json.investment_query }}",
        "operation": "search"
      },
      "typeVersion": 1
    },
    {
      "id": "dea85597-d922-40e3-a560-d176cee56a1e",
      "name": "Combine Ticker Research",
      "type": "n8n-nodes-base.code",
      "position": [
        3248,
        1120
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst watchlist = items.map(function(item) {\n  return {\n    ticker: item.json.ticker || 'Unknown',\n    sources: item.json.organic || item.json.results || item.json.data || []\n  };\n});\n\nconst first = items.length > 0 ? items[0].json : {};\n\nreturn [\n  {\n    json: {\n      report_date: new Date().toISOString().split('T')[0],\n      watchlist: watchlist,\n      email_to: first.email_to || 'user@example.com',\n      email_from: first.email_from || 'user@example.com',\n      email_subject_prefix: first.email_subject_prefix || 'Daily Investment Research Report'\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "e86f05d8-2966-40cd-b42f-40e3f7c01363",
      "name": "OpenAI - Create Full Watchlist Email Report",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        3472,
        1120
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.4-mini",
          "cachedResultName": "GPT-5.4-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=You are an investment research assistant.\n\nYou will receive search and scraped web results for multiple stock tickers. Your job is to turn the results into one clean Markdown email report for the full watchlist.\n\nImportant rules:\n- Create only one complete report for the full watchlist.\n- Do not repeat the title, generated date, executive summary, or disclaimer for each ticker.\n- Do not give direct buy, sell, or hold advice.\n- Do not say \"invest in this\" or \"sell this\".\n- Do not predict stock prices.\n- Do not invent numbers or facts.\n- Use only the information provided in the input.\n- If information is missing, write \"Not found in provided sources.\"\n- Keep the report concise but useful.\n- Group the report by ticker/company.\n- Include source links under each company.\n- For each company, include a neutral \"Signal Summary\" with: Opportunity Signals, Risk / Exit Watch Signals, and Research Priority.\n- Research Priority may be High / Medium / Low, but it must not be framed as financial advice.\n\nReport date:\n{{ $json.report_date }}\n\nInput data:\n{{ JSON.stringify($json.watchlist) }}\n\nCreate the Markdown report using this structure:\n\n# Daily Investment Research Report\n\nGenerated on: {{ $json.report_date }}\n\n## Executive Summary\n\nWrite 5-7 bullets summarizing the most important findings across all tickers.\n\n## Watchlist Signal Table\n\nCreate a simple Markdown table with these columns:\n| Ticker | Opportunity Signals | Risk / Exit Watch Signals | Research Priority |\n\nImportant: The table must not include Buy, Sell, or Hold recommendations.\n\n## Ticker-by-Ticker Analysis\n\nFor each ticker or company found in the input, create this section:\n\n### [Company Name] ([Ticker if available])\n\n#### Key Sources Reviewed\n- [Source title](Source URL)\n- [Source title](Source URL)\n\n#### Recent Updates\nSummarize the most important recent updates from the sources.\n\n#### Opportunity Signals\n- Bullet 1\n- Bullet 2\n- Bullet 3\n\n#### Risk / Exit Watch Signals\n- Bullet 1\n- Bullet 2\n- Bullet 3\n\n#### Financial / Earnings Signals\nSummarize any revenue, earnings, margin, guidance, or filing-related information found.\n\n#### Competitive Position\nSummarize any information about competitors, market position, product demand, or sector trends.\n\n#### Investor Questions to Investigate Next\n- Question 1\n- Question 2\n- Question 3\n\n#### Research Confidence\nChoose one: High / Medium / Low\n\nExplain the confidence rating in one short sentence.\n\n---\n\n## Cross-Watchlist Themes\n\nSummarize patterns across all companies, such as AI demand, data center growth, margin pressure, regulatory risk, leadership changes, earnings momentum, and competitive pressure.\n\n## Red Flags to Monitor\n\nList the most important risks found across the full watchlist.\n\n## Follow-Up Research Checklist\n\n- Review latest 10-K or 10-Q filings\n- Compare latest earnings call transcripts\n- Check revenue guidance\n- Review analyst downgrades or upgrades\n- Look for lawsuits, investigations, layoffs, or executive changes\n\n## Disclaimer\n\nThis report is generated from public web research and is for research automation only. It is not financial advice. It does not provide buy, sell, or hold recommendations.\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "b04c6cba-a4f4-4909-ab83-4c4b95c8decd",
      "name": "Build HTML Email Body",
      "type": "n8n-nodes-base.code",
      "position": [
        3824,
        1120
      ],
      "parameters": {
        "jsCode": "const output = $json.output && $json.output[0] && $json.output[0].content && $json.output[0].content[0] && $json.output[0].content[0].text;\nconst markdown = output || $json.text || '';\n\nfunction escapeHtml(str) {\n  return String(str)\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;');\n}\n\nlet html = escapeHtml(markdown);\n\nhtml = html\n  .replace(/\\*\\*(.*?)\\*\\*/gim, '<strong>$1</strong>')\n  .replace(/\\[(.*?)\\]\\((.*?)\\)/gim, '<a href=\"$2\">$1</a>');\n\nhtml = html\n  .replace(/^#### (.*$)/gim, '<h4>$1</h4>')\n  .replace(/^### (.*$)/gim, '<h3>$1</h3>')\n  .replace(/^## (.*$)/gim, '<h2>$1</h2>')\n  .replace(/^# (.*$)/gim, '<h1>$1</h1>')\n  .replace(/^---$/gim, '<hr />');\n\nhtml = html.replace(/((?:^|\\n)\\|.+\\|\\n\\|[-:\\s|]+\\|\\n(?:\\|.+\\|\\n?)+)/g, function(tableBlock) {\n  const rows = tableBlock.trim().split('\\n');\n  const headers = rows[0].split('|').slice(1, -1).map(function(h) { return h.trim(); });\n  const bodyRows = rows.slice(2).map(function(row) {\n    return row.split('|').slice(1, -1).map(function(c) { return c.trim(); });\n  });\n  const thead = '<thead><tr>' + headers.map(function(h) { return '<th>' + h + '</th>'; }).join('') + '</tr></thead>';\n  const tbody = '<tbody>' + bodyRows.map(function(cols) {\n    return '<tr>' + cols.map(function(c) { return '<td>' + c + '</td>'; }).join('') + '</tr>';\n  }).join('') + '</tbody>';\n  return '<table>' + thead + tbody + '</table>';\n});\n\nhtml = html.replace(/(?:^|\\n)(- .*(?:\\n- .*)*)/g, function(match) {\n  const items = match\n    .trim()\n    .split('\\n')\n    .map(function(line) { return '<li>' + line.replace(/^- /, '') + '</li>'; })\n    .join('');\n  return '<ul>' + items + '</ul>';\n});\n\nhtml = html\n  .split('\\n')\n  .map(function(line) {\n    const trimmed = line.trim();\n    if (!trimmed) return '';\n    if (\n      trimmed.startsWith('<h') ||\n      trimmed.startsWith('<ul') ||\n      trimmed.startsWith('<li') ||\n      trimmed.startsWith('</ul') ||\n      trimmed.startsWith('<hr') ||\n      trimmed.startsWith('<table') ||\n      trimmed.startsWith('<thead') ||\n      trimmed.startsWith('<tbody') ||\n      trimmed.startsWith('<tr') ||\n      trimmed.startsWith('<th') ||\n      trimmed.startsWith('<td') ||\n      trimmed.startsWith('</table')\n    ) {\n      return trimmed;\n    }\n    return '<p>' + trimmed + '</p>';\n  })\n  .join('\\n');\n\nconst reportDate = new Date().toISOString().split('T')[0];\nconst subjectPrefix = $json.email_subject_prefix || 'Daily Investment Research Report';\n\nlet emailHtml = '<!doctype html>';\nemailHtml += '<html><head><meta charset=\"utf-8\"></head>';\nemailHtml += '<body style=\"margin:0; padding:0; background:#f3f4f6; font-family:Arial, Helvetica, sans-serif; color:#111827;\">';\nemailHtml += '<div style=\"max-width:820px; margin:0 auto; padding:24px 14px;\">';\nemailHtml += '<div style=\"background:#ffffff; border:1px solid #e5e7eb; border-radius:12px; overflow:hidden;\">';\nemailHtml += '<div style=\"padding:22px 24px; border-bottom:3px solid #111827;\">';\nemailHtml += '<div style=\"font-size:11px; letter-spacing:0.12em; text-transform:uppercase; color:#6b7280; margin-bottom:8px;\">Automated Investment Research</div>';\nemailHtml += '<h1 style=\"font-size:26px; line-height:1.2; margin:0 0 6px 0; color:#0f172a;\">Daily Investment Research Report</h1>';\nemailHtml += '<div style=\"font-size:12px; color:#6b7280;\">Generated on ' + reportDate + '</div>';\nemailHtml += '</div>';\nemailHtml += '<div style=\"padding:16px 24px; background:#f8fafc; border-bottom:1px solid #e5e7eb; font-size:13px; color:#374151;\">';\nemailHtml += 'This automated email summarizes opportunity signals, risk signals, and research priorities from public sources. It is not financial advice and does not provide buy, sell, or hold recommendations.';\nemailHtml += '</div>';\nemailHtml += '<div class=\"report-content\" style=\"padding:8px 24px 24px 24px; font-size:14px; line-height:1.55;\">' + html + '</div>';\nemailHtml += '</div></div></body></html>';\n\nconst styledHtml = emailHtml\n  .replace(/<h1>/g, '<h1 style=\"font-size:24px; line-height:1.2; margin:18px 0 8px; color:#0f172a;\">')\n  .replace(/<h2>/g, '<h2 style=\"font-size:18px; margin:24px 0 10px; padding-bottom:6px; border-bottom:1px solid #e5e7eb; color:#111827;\">')\n  .replace(/<h3>/g, '<h3 style=\"font-size:16px; margin:22px 0 10px; padding:10px 12px; border-left:4px solid #111827; background:#f9fafb; color:#111827;\">')\n  .replace(/<h4>/g, '<h4 style=\"font-size:12px; margin:16px 0 8px; color:#374151; text-transform:uppercase; letter-spacing:0.05em;\">')\n  .replace(/<p>/g, '<p style=\"margin:7px 0;\">')\n  .replace(/<ul>/g, '<ul style=\"margin:8px 0 14px 20px; padding:0;\">')\n  .replace(/<li>/g, '<li style=\"margin:4px 0;\">')\n  .replace(/<a /g, '<a style=\"color:#1d4ed8; text-decoration:none; word-break:break-word;\" ')\n  .replace(/<hr \\/>/g, '<hr style=\"border:0; border-top:1px solid #d1d5db; margin:24px 0;\" />')\n  .replace(/<table>/g, '<table style=\"width:100%; border-collapse:collapse; margin:12px 0 18px; font-size:13px;\">')\n  .replace(/<th>/g, '<th style=\"border:1px solid #e5e7eb; padding:8px; text-align:left; background:#f9fafb;\">')\n  .replace(/<td>/g, '<td style=\"border:1px solid #e5e7eb; padding:8px; vertical-align:top;\">');\n\nreturn [\n  {\n    json: {\n      email_to: $('Split Tickers').first().json.email_to,\n      email_from: $('Split Tickers').first().json.email_from,\n      email_subject: subjectPrefix + ' - ' + reportDate,\n      email_html: styledHtml\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "00c0cd82-b442-494f-a458-8259609d7b9d",
      "name": "Send HTML Email via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4048,
        1120
      ],
      "parameters": {
        "sendTo": "={{ $json.email_to }}",
        "message": "={{ $json.email_html }}",
        "options": {
          "senderName": "Investment Research Bot"
        },
        "subject": "={{ $json.email_subject }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "01bbe6df-f200-4d8d-9d69-e0cfae8d0150",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        912
      ],
      "parameters": {
        "width": 528,
        "height": 320,
        "content": "## Daily investment research email\n\n### How it works\nThis workflow researches a stock watchlist with Olostep, summarizes the findings with OpenAI GPT-5.4-mini, and sends one styled Gmail report.\n\n### Setup steps\n- [ ] Add Olostep, OpenAI, and Gmail credentials.\n- [ ] Update the `Investment Watchlist` node with tickers and email fields.\n- [ ] Run `Manual Test Trigger` and review the email before activating.\n\n### Customization\nChange the ticker list, schedule, prompt, subject, or HTML styling to match your research workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "2f843fc6-3fe4-4602-bce7-0ce506c29a52",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        1248
      ],
      "parameters": {
        "color": 4,
        "width": 528,
        "height": 80,
        "content": "### How can we improve this workflow?\n### Share feedback on the n8n template page or repository."
      },
      "typeVersion": 1
    },
    {
      "id": "07ecc92e-0f34-4542-b8b1-fa7b89e8a045",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2272,
        912
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 464,
        "content": "## Trigger and configure\n\nStarts the workflow and prepares the stock watchlist for research."
      },
      "typeVersion": 1
    },
    {
      "id": "050aa094-de32-45b6-9314-532d31fa3f9a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2752,
        912
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 464,
        "content": "## Research investment sources\n\nSearches public investment sources and combines per-ticker results."
      },
      "typeVersion": 1
    },
    {
      "id": "93a026a3-4562-422d-a868-32d2ba3bb27a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3440,
        912
      ],
      "parameters": {
        "color": 7,
        "width": 768,
        "height": 464,
        "content": "## Generate and send report\n\nCreates the neutral watchlist report, formats it as HTML, and sends it via Gmail."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "connections": {
    "Split Tickers": {
      "main": [
        [
          {
            "node": "Olostep Search - Investment Sources",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Test Trigger": {
      "main": [
        [
          {
            "node": "Investment Watchlist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Investment Watchlist": {
      "main": [
        [
          {
            "node": "Split Tickers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build HTML Email Body": {
      "main": [
        [
          {
            "node": "Send HTML Email via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Ticker Research": {
      "main": [
        [
          {
            "node": "OpenAI - Create Full Watchlist Email Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekday Market Open Trigger": {
      "main": [
        [
          {
            "node": "Investment Watchlist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Olostep Search - Investment Sources": {
      "main": [
        [
          {
            "node": "Combine Ticker Research",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI - Create Full Watchlist Email Report": {
      "main": [
        [
          {
            "node": "Build HTML Email Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This n8n template researches a stock watchlist with Olostep, turns the results into a concise OpenAI-generated investment research report, converts the report into a styled HTML email, and sends it with Gmail.

Source: https://n8n.io/workflows/15387/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

AI-Powered LinkedIn Content Engine (n8n + OpenAI + Perplexity + Replicate). Uses openAi, perplexity, gmail. Scheduled trigger; 28 nodes.

OpenAI, Perplexity, Gmail
AI & RAG

What This Workflow Does: Generates original, research-based LinkedIn posts Combines AI insights with personal storytelling Includes human-in-the-loop selection & revision steps Automatically creates a

OpenAI, Perplexity, Gmail
AI & RAG

AI-Powered LinkedIn Content Engine (n8n + OpenAI + Perplexity + Replicate). Uses openAi, perplexity, gmail. Scheduled trigger; 28 nodes.

OpenAI, Perplexity, Gmail
AI & RAG

This n8n template demonstrates how to automate the full production cycle of a professional weekly newsletter. It combines AI-powered market research, editorial drafting, compliance validation, and an

Gmail, Perplexity, OpenAI
AI & RAG

It’s very important to come prepared to Sales calls. This often means a lot of manual research about the person you’re calling with. This workflow delivers a summary of the latest social media activit

Google Calendar, HTTP Request, Clearbit +2