This workflow corresponds to n8n.io template #15669 — we link there as the canonical source.
This workflow follows the Agent → HTTP Request 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 →
{
"id": "X4ceJVR1FDKLRw1h",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Top Gainers / Losers \u2192 Insight Generator",
"tags": [],
"nodes": [
{
"id": "e06ff4cb-666a-4b79-8300-dd6c2aaea866",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1184,
272
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "1f197edd-5f33-4b72-8808-46d9264c1072",
"name": "Start Market Analysis",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-464,
48
],
"parameters": {},
"typeVersion": 1
},
{
"id": "e06e196b-b51a-40fe-b039-2c8045e7e5b4",
"name": "Fetch Market Data",
"type": "n8n-nodes-base.httpRequest",
"position": [
-240,
48
],
"parameters": {
"url": "https://www.alphavantage.co/query?",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "apikey",
"value": "P7JC17Y2D51A4CYI"
},
{
"name": "function",
"value": "TOP_GAINERS_LOSERS"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "1d205b8f-dccd-42a5-a45b-2d3f018921c3",
"name": "Calculate Market Sentiment",
"type": "n8n-nodes-base.code",
"position": [
-16,
48
],
"parameters": {
"jsCode": "// Get the data from the HTTP Request node\nconst data = $input.first().json;\n\n// Function to calculate average change percentage\nconst getAverageChange = (array) => {\n if (!array || array.length === 0) return 0;\n const sum = array.slice(0, 10).reduce((acc, stock) => {\n // Remove the '%' sign and convert to a number\n return acc + parseFloat(stock.change_percentage.replace('%', ''));\n }, 0);\n return (sum / Math.min(array.length, 10)).toFixed(2);\n};\n\n// Calculate metrics\nconst avgGainerMove = getAverageChange(data.top_gainers);\nconst avgLoserMove = getAverageChange(data.top_losers);\nconst marketSentiment = avgGainerMove > Math.abs(avgLoserMove) ? \"Bullish\" : \"Bearish\";\n\n// Return the enhanced data\nreturn {\n market_summary: {\n sentiment: marketSentiment,\n average_gainer_percent: avgGainerMove + \"%\",\n average_loser_percent: avgLoserMove + \"%\",\n top_performer: data.top_gainers[0].ticker,\n worst_performer: data.top_losers[0].ticker,\n timestamp: data.last_updated\n },\n // Keep the original data just in case the AI needs it\n raw_gainers: data.top_gainers.slice(0, 5), \n raw_losers: data.top_losers.slice(0, 5)\n};"
},
"typeVersion": 2
},
{
"id": "56cf1091-1572-4b4f-8e81-6e45280cacc7",
"name": "API Rate Limit Guard",
"type": "n8n-nodes-base.wait",
"position": [
208,
48
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "d3a1b39e-d25a-44e9-a1af-3339a941bcdc",
"name": "Sanitize Stock Ticker",
"type": "n8n-nodes-base.code",
"position": [
432,
48
],
"parameters": {
"jsCode": "// Get the ticker from the market summary\nlet ticker = $input.first().json.market_summary.top_performer;\n\n// Remove any special characters (like ^) so the News API doesn't crash\nlet cleanTicker = ticker.replace(/[^a-zA-Z0-9]/g, \"\");\n\n// Return the cleaned ticker back to the flow\nreturn {\n market_summary: $input.first().json.market_summary,\n clean_ticker: cleanTicker\n};"
},
"typeVersion": 2
},
{
"id": "defbbfaf-a5eb-49f6-9607-e50b0474b0db",
"name": "Get Ticker News Context",
"type": "n8n-nodes-base.httpRequest",
"position": [
656,
48
],
"parameters": {
"url": "=https://www.alphavantage.co/query",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "function",
"value": "NEWS_SENTIMENT"
},
{
"name": "tickers",
"value": "={{ $json.clean_ticker }}"
},
{
"name": "apikey",
"value": "P7JC17Y2D51A4CYI"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Accept",
"value": "application/json"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "94b8e72d-89b2-418b-a238-44ddd9b35046",
"name": "Keep Top 3 Headlines",
"type": "n8n-nodes-base.limit",
"position": [
880,
48
],
"parameters": {
"maxItems": 3
},
"typeVersion": 1
},
{
"id": "00c3686c-bdf8-40fc-9c7e-8379e3999101",
"name": "Generate Financial Insight",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1104,
48
],
"parameters": {
"text": "=Analyze today's market based on the following data:\n\nMarket Summary: The overall sentiment is {{ $('Sanitize Stock Ticker').item.json.market_summary.sentiment }}.\nTop Gainer: {{ $('Sanitize Stock Ticker').item.json.market_summary.top_performer }} is up {{ $('Sanitize Stock Ticker').item.json.market_summary.average_gainer_percent }}.\nNews Context: Headlines: \"{{ $json[\"feed\"][0][\"title\"] }}\" and \"{{ $json[\"feed\"][1][\"title\"] }}\".",
"options": {
"systemMessage": "You are a financial analyst. Here is today's stock market data:\nTop Gainers: {{ JSON.stringify($json.top_gainers) }}\nTop Losers: {{ JSON.stringify($json.top_losers) }}\n\nAnalyze and provide:\n1. Key patterns (sector trends, rallies, declines)\n2. Possible reasons (market sentiment, news, sector movement)\n3. Short summary (3-4 lines)\n\nKeep it concise and professional."
},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "daddd495-d029-458e-85c5-f99c30cb9242",
"name": "Format Slack Report",
"type": "n8n-nodes-base.set",
"position": [
1456,
48
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "6160e65c-e1ed-4f56-b633-0228154b6d1b",
"name": "final_report",
"type": "string",
"value": "={{ $json.output.replace(/1\\.\\s*|2\\.\\s*|3\\.\\s*/g, \"\\n\\n\") }}"
},
{
"id": "67240c8d-da18-432b-9852-55a+1234567890c",
"name": "formatted_timestamp",
"type": "string",
"value": "={{ $('Calculate Market Sentiment').item.json.market_summary.timestamp }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "9ffd1e59-995f-40fe-96b8-584b219ebecc",
"name": "Post to Portfolio Channel",
"type": "n8n-nodes-base.slack",
"position": [
1680,
48
],
"parameters": {
"text": "= *Daily Market Insight Report*\n---\n{{ $json.final_report }}\n\n *Data Timestamp:* {{ $json.formatted_timestamp }}",
"user": {
"__rl": true,
"mode": "id",
"value": "U0AP17N3QRY"
},
"select": "user",
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "0376a1a6-f90c-446b-8460-904595ddc325",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-976,
-400
],
"parameters": {
"width": 448,
"height": 560,
"content": "## Project: Top Gainers / Losers \u2192 Insight Generator\n\n## How it works: \nThis workflow automates daily financial analysis. it fetches top market movers from Alpha Vantage, calculates macro sentiment via JavaScript and identifies the #1 gainer. It then researches live news for that specific stock and uses Gemini AI to explain the \"Why\" behind the price action, delivering a structured report to Slack.\n\n## Setup Steps:\n\nCredentials: Add your Alpha Vantage API key to both HTTP nodes and your Google Gemini API key to the Chat Model.\n\nSlack: Connect your Slack account and select a destination channel.\n\nSchedule: Change the \"Start\" node to a Schedule trigger to run automatically at market close.\n\nActivate: Hit the 'Active' toggle in the top right."
},
"typeVersion": 1
},
{
"id": "e1941435-4e18-4325-93c7-5e25356f842a",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
-128
],
"parameters": {
"color": 7,
"width": 624,
"height": 336,
"content": "## Group A: Data Acquisition & Prep\n(Group Nodes 1, 2 and 3)\n\nFetches raw market data and uses a Code node to calculate average gains and overall \"Bullish/Bearish\" sentiment for the day."
},
"typeVersion": 1
},
{
"id": "c54788ab-eefe-4720-8115-5e962dd33d92",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
176,
-128
],
"parameters": {
"color": 7,
"width": 848,
"height": 336,
"content": "## GroupB: Research & Sanitization\n(Group Nodes 4, 5, 6 and 7)\n\nProtects API limits with a Wait node, cleans ticker symbols (e.g., removing '^') and fetches the top 3 relevant news headlines for the lead stock."
},
"typeVersion": 1
},
{
"id": "6a438269-7aed-427a-8f72-00926182b9e4",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1072,
-128
],
"parameters": {
"color": 7,
"width": 736,
"height": 352,
"content": "## Group C: AI Analysis & Delivery\n(Group Nodes 8, 9, 10 and 11)\n\nPasses the cleaned data to Gemini to generate a structured financial report. The Edit Fields node then formats the text into a clean layout for Slack."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "dc8b399b-4502-4aff-8713-f148619132fc",
"connections": {
"Fetch Market Data": {
"main": [
[
{
"node": "Calculate Market Sentiment",
"type": "main",
"index": 0
}
]
]
},
"Format Slack Report": {
"main": [
[
{
"node": "Post to Portfolio Channel",
"type": "main",
"index": 0
}
]
]
},
"API Rate Limit Guard": {
"main": [
[
{
"node": "Sanitize Stock Ticker",
"type": "main",
"index": 0
}
]
]
},
"Keep Top 3 Headlines": {
"main": [
[
{
"node": "Generate Financial Insight",
"type": "main",
"index": 0
}
]
]
},
"Sanitize Stock Ticker": {
"main": [
[
{
"node": "Get Ticker News Context",
"type": "main",
"index": 0
}
]
]
},
"Start Market Analysis": {
"main": [
[
{
"node": "Fetch Market Data",
"type": "main",
"index": 0
}
]
]
},
"Get Ticker News Context": {
"main": [
[
{
"node": "Keep Top 3 Headlines",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Generate Financial Insight",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Calculate Market Sentiment": {
"main": [
[
{
"node": "API Rate Limit Guard",
"type": "main",
"index": 0
}
]
]
},
"Generate Financial Insight": {
"main": [
[
{
"node": "Format Slack Report",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googlePalmApislackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
> Alpha Vantage, Google Gemini AI and Slack Integration
Source: https://n8n.io/workflows/15669/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
CV → Match → Screen → Decide, all automated
This workflow analyzes any npm package and delivers a data-driven recommendation using Firecrawl + APIs + AI reasoning.
This workflow provides a fully automated multi-chain crypto portfolio tracking system powered by AI.
Stop drowning in job applications. This workflow transforms your hiring process from a manual, time-consuming data-entry task into an automated, intelligent screening system.
Customer support agent. Uses httpRequest, googleSheets, memoryBufferWindow, googleSheetsTool. Event-driven trigger; 19 nodes.