This workflow corresponds to n8n.io template #4867 — we link there as the canonical source.
This workflow follows the HTTP Request → 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 →
{
"id": "e5XxiuYXr5atCH64",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Stock Analysis Assistant",
"tags": [
{
"id": "TkUb5sI0Ae0hwCo3",
"name": "Agent",
"createdAt": "2025-04-07T21:00:21.151Z",
"updatedAt": "2025-04-07T21:00:21.151Z"
},
{
"id": "xhCApXrnlelxaW2i",
"name": "Stock",
"createdAt": "2025-06-09T04:02:42.364Z",
"updatedAt": "2025-06-09T04:02:42.364Z"
},
{
"id": "eZArPFfgyfBReNUS",
"name": "AlpacaAPI",
"createdAt": "2025-06-09T04:02:47.415Z",
"updatedAt": "2025-06-09T04:02:47.415Z"
}
],
"nodes": [
{
"id": "f9e2b1a6-4bc4-429c-a516-78fc440cb259",
"name": "Ticker List",
"type": "n8n-nodes-base.set",
"position": [
800,
0
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "{\n \"symbols\": \"AAPL,MSFT,NVDA,TSLA,AMZN,GOOGL,META,JPM,XOM,UNH,GME\"\n}\n"
},
"typeVersion": 3.4
},
{
"id": "46c712d0-8e65-4da0-bdbc-9eadf4213f2f",
"name": "Fetch Stock Data",
"type": "n8n-nodes-base.httpRequest",
"position": [
1020,
0
],
"parameters": {
"url": "=https://data.alpaca.markets/v2/stocks/bars",
"options": {},
"sendQuery": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpCustomAuth",
"queryParameters": {
"parameters": [
{
"name": "symbols",
"value": "={{ $json.symbols }}"
},
{
"name": "timeframe",
"value": "1Day"
},
{
"name": "limit",
"value": "1000"
},
{
"name": "feed",
"value": "iex"
},
{
"name": "=start",
"value": "={{ new Date(Date.now() - 100 * 24 * 60 * 60 * 1000).toISOString().split('T')[0] }}"
},
{
"name": "end",
"value": "={{ new Date().toISOString().split('T')[0] }}"
}
]
}
},
"credentials": {
"httpCustomAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "e8d96c0c-e927-4676-a02f-7729c0126165",
"name": "Interpret Data",
"type": "n8n-nodes-base.code",
"position": [
1240,
0
],
"parameters": {
"language": "python",
"pythonCode": "import pandas as pd\nimport numpy as np\nimport json\n\nbars_by_symbol = items[0]['json']['bars']\nstocks = []\n\nfor symbol, bars in bars_by_symbol.items():\n closes = [bar['c'] for bar in bars if 'c' in bar]\n if len(closes) < 30:\n continue\n\n df = pd.DataFrame({'close': closes})\n\n # RSI(14)\n delta = df['close'].diff()\n gain = delta.clip(lower=0)\n loss = -delta.clip(upper=0)\n avg_gain = gain.rolling(14).mean()\n avg_loss = loss.rolling(14).mean()\n rs = avg_gain / avg_loss\n df['rsi'] = 100 - (100 / (1 + rs))\n\n # MACD (12,26,9)\n ema12 = df['close'].ewm(span=12, adjust=False).mean()\n ema26 = df['close'].ewm(span=26, adjust=False).mean()\n df['macd'] = ema12 - ema26\n df['signal'] = df['macd'].ewm(span=9, adjust=False).mean()\n\n latest = df.iloc[-1]\n rsi = latest['rsi']\n macd = latest['macd']\n signal = latest['signal']\n\n status = \"Hold\"\n if rsi < 30 and macd > signal:\n status = \"Buy\"\n elif rsi > 70 and macd < signal:\n status = \"Sell\"\n\n stocks.append({\n \"ticker\": symbol,\n \"rsi\": round(float(rsi), 2),\n \"macd\": round(float(macd), 2),\n \"signal\": round(float(signal), 2),\n \"status\": status\n })\n\nreturn [{\n \"json\": {\n \"summary\": json.dumps({\n \"stocks\": stocks\n }, separators=(',', ':')),\n \"stocks\": stocks\n }\n}]\n"
},
"typeVersion": 2
},
{
"id": "5ace21ee-80b0-4d79-be68-ded17b53b5a2",
"name": "Stock Analysis Assistant",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1440,
0
],
"parameters": {
"text": "=Here is the technical indicator data as JSON:\n\n{{ $json.summary }}\n\nPulled as of {{ $now }}",
"prompt": "define",
"options": {},
"resource": "assistant",
"assistantId": {
"mode": "list",
"value": "REDACTED_ASSISTANT_ID",
"cachedResultName": "REDACTED_ASSISTANT"
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "97f8d2af-02a9-4f93-8bf7-ee083b13dccf",
"name": "Send Summary to User(s)",
"type": "n8n-nodes-base.slack",
"position": [
1816,
0
],
"parameters": {
"text": "={{ $json.output }}",
"user": {
"mode": "list",
"value": "REDACTED_USER_ID",
"cachedResultName": "REDACTED_USER"
},
"select": "user",
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.3
},
{
"id": "21b091f5-ce81-4d98-8978-f7193734a72c",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
120,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 30 6-14 * * 1-5"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "94804d45-b868-4501-a53c-0a1063768f14",
"name": "Check if Market is open",
"type": "n8n-nodes-base.if",
"position": [
560,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "acca2d72-d9db-436d-aee8-81a3a359fe85",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.is_open }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "8366acca-42ff-4106-8b37-316727ac8963",
"name": "Market is Closed",
"type": "n8n-nodes-base.noOp",
"position": [
800,
200
],
"parameters": {},
"typeVersion": 1
},
{
"id": "ee50cf08-efe2-4886-8527-23c069495afd",
"name": "Check Market Status",
"type": "n8n-nodes-base.httpRequest",
"position": [
360,
0
],
"parameters": {
"url": "https://paper-api.alpaca.markets/v2/clock",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpCustomAuth"
},
"credentials": {
"httpCustomAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "97de7640-5be5-4821-9cea-a8d481590256",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-640,
-360
],
"parameters": {
"width": 660,
"content": "# \ud83e\udde0 Stock Analysis Assistant\n\nThis workflow analyzes selected S&P 500 stocks using RSI and MACD indicators, summarizes the insights into plain English, and posts an update to Slack every hour during U.S. market hours (Mon\u2013Fri)."
},
"typeVersion": 1
},
{
"id": "4c40864c-ad6d-420f-88b8-a497d7c71a5d",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
40,
-360
],
"parameters": {
"color": 7,
"height": 700,
"content": "## \ud83d\udcc5 Schedule Trigger\n\n**Node:** `Schedule Trigger` \nRuns every hour between 6:30 AM and 2:30 PM (PST), Monday to Friday. \n**Cron Expression:** `0 30 6-14 * * 1-5`\n\n\u23f0 Triggers analysis only during U.S. stock market hours."
},
"typeVersion": 1
},
{
"id": "28ee034a-cb6a-4a54-8ce1-fef5e439e2de",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
280,
-360
],
"parameters": {
"color": 7,
"width": 460,
"height": 700,
"content": "## \ud83c\udfdb\ufe0f Market Status Check\n\n**Node:** `Check Market Status` \nEndpoint: `https://paper-api.alpaca.markets/v2/clock`\n\nChecks if the market is open using Alpaca\u2019s `/clock` endpoint.\n\n**Node:** `Check if Market is open` \n- \u2705 If true \u2192 continue \n- \u274c If false \u2192 exit gracefully via the \u201cMarket is Closed\u201d NoOp node"
},
"typeVersion": 1
},
{
"id": "ab88e6c4-bafb-47d6-9292-b54850f1d984",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
740,
-360
],
"parameters": {
"color": 4,
"width": 220,
"height": 540,
"content": "## \ud83d\udcc8 Ticker Setup\n\n**Node:** `Ticker List` \nSets the stock symbols to be analyzed.\n\n\ud83d\udccc You can update this list to monitor different stocks."
},
"typeVersion": 1
},
{
"id": "01892c69-4c22-4c78-a1db-1add2d06993c",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
960,
-360
],
"parameters": {
"color": 4,
"width": 220,
"height": 540,
"content": "## \ud83d\udd17 Fetch Stock Data\n\n**Node:** `Fetch Stock Data` \nCalls Alpaca\u2019s `/v2/stocks/bars` endpoint with:\n- `symbols`: from `Ticker List`\n- `timeframe`: `1Day`\n- `limit`: `1000`\n- `feed`: `iex` (avoid SIP permission error)\n- `start`: 100 days ago\n- `end`: today"
},
"typeVersion": 1
},
{
"id": "a1b98ff6-b033-4f0c-90c6-b6bf2ea0e461",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1180,
-360
],
"parameters": {
"color": 4,
"width": 220,
"height": 540,
"content": "## \ud83e\uddee Interpret Data\n\n**Node:** `Interpret Data` \nPython code calculates:\n- RSI(14)\n- MACD(12,26,9)\n- Decision status: `\"Buy\"`, `\"Hold\"`, or `\"Sell\"`\n\nOutputs:\n- `stocks`: a list of indicator values and status\n- `summary`: JSON string version for GPT"
},
"typeVersion": 1
},
{
"id": "0ac7e6ad-405e-46b6-81b9-3367c7793136",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1400,
-360
],
"parameters": {
"color": 4,
"width": 360,
"height": 540,
"content": "## \ud83e\udd16 AI Assistant Summary\n\n**Node:** `Stock Analysis Assistant` \nUses a custom OpenAI assistant to:\n- Group stocks into categories\n- Provide commentary in plain English\n- Teach users simple market behaviors\n\nPrompt includes:\n- Stock JSON (`summary`)\n- Timestamp (`$now`)\n\n\ud83d\udccc Uses Slack-friendly markdown output."
},
"typeVersion": 1
},
{
"id": "10b73555-9619-4327-beac-d36a5a88f844",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
740,
180
],
"parameters": {
"color": 3,
"width": 220,
"content": ""
},
"typeVersion": 1
},
{
"id": "91c98665-4226-4579-a9df-2dd4ad137638",
"name": "End of Flow",
"type": "n8n-nodes-base.noOp",
"position": [
2040,
0
],
"parameters": {},
"typeVersion": 1
},
{
"id": "f11bdac9-2fbe-4ea5-a470-d89d26aa01ba",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1760,
-360
],
"parameters": {
"color": 4,
"width": 220,
"height": 540,
"content": "## \ud83d\udcac Post to Slack\n\n**Node:** `Send Summary to User(s)` \nSends the GPT-generated summary to Slack using:\n```js\n{{ $json.output }}\n```\n\u2699\ufe0f Configured with the appropriate Slack user or channel."
},
"typeVersion": 1
},
{
"id": "8221dafd-302c-4bbe-9cea-25bdbe980acb",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1980,
-360
],
"parameters": {
"color": 4,
"width": 220,
"height": 540,
"content": ""
},
"typeVersion": 1
},
{
"id": "d492d1bc-99ba-43da-bf15-1cbe11badb13",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-640,
-180
],
"parameters": {
"color": 5,
"width": 660,
"height": 940,
"content": "## \ud83e\udd16 AI Assistant Prompt\n\nYou are a financial assistant writing a quick, readable market update for a general audience. Your job is to help people understand how well-known stocks are behaving \u2014 even if they aren\u2019t professional traders.\n\nYou\u2019ll be given:\n\nA list of stocks with technical indicators (e.g., momentum data)\nA timestamp (in RFC 3339 or ISO format) for when the data was pulled.\n\ud83d\udccc Your task:\nGroup the stocks into three categories:\n\ud83d\udfe2 Buy Watchlist \u2013 Stocks showing signs of recovery or upward momentum\n\u26aa Neutral Hold \u2013 Stocks with steady or unclear direction\n\ud83d\udd34 Caution / Sell \u2013 Stocks that appear overbought or may pull back\nFor each stock:\nWrite a short, plain-language insight about what\u2019s happening\nUse familiar terms like \u201cgaining steam,\u201d \u201ccooling off,\u201d or \u201cshowing hesitation\u201d\nAvoid technical jargon like RSI or MACD unless context makes it helpful\nAdd a helpful tip or comment for each stock (e.g.,\n\u201cThis pattern often signals hesitation\u201d or\n\u201cThis dip might attract bargain hunters\u201d)\nFinish with a summary line using the timestamp like this:\nSummary as of October 2, 2025 \u2013 Most stocks were stable with one or two worth watching.\n\ud83d\udce6 Respond in Slack Markdown Only:\nExample Format:\n\n*\ud83d\udcca Market Summary (as of October 2, 2025)*\n\n\ud83d\udfe2 *Buy Watchlist* \n\u2022 TSLA \u2013 Recovering after a dip; gaining steam. This type of rebound often attracts early buyers.\n\n\u26aa *Neutral Hold* \n\u2022 AAPL \u2013 Holding steady. This often means the market is waiting on new developments. \n\u2022 GOOGL \u2013 Moving sideways. A sign of consolidation before potential breakout. \n\u2022 MSFT \u2013 Little movement. Could be digesting prior gains. \n\u2022 NVDA \u2013 Slight back-and-forth. May indicate indecision in the market.\n\n\ud83d\udd34 *Caution / Sell* \n\u2022 None at this time.\n\n_Summary as of October 2, 2025: Most stocks appear steady. TSLA could be one to watch if momentum holds._\n\ud83d\udeab Do NOT:\nReturn raw JSON\nUse code blocks unless formatting Slack markdown (no YAML or tags)\nUse technical finance language unless simplified"
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"timezone": "America/Los_Angeles",
"callerPolicy": "workflowsFromSameOwner",
"executionOrder": "v1"
},
"versionId": "0523c0a7-8874-4eff-bcd7-cf3d9ab7c362",
"connections": {
"Ticker List": {
"main": [
[
{
"node": "Fetch Stock Data",
"type": "main",
"index": 0
}
]
]
},
"Interpret Data": {
"main": [
[
{
"node": "Stock Analysis Assistant",
"type": "main",
"index": 0
}
]
]
},
"Fetch Stock Data": {
"main": [
[
{
"node": "Interpret Data",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Check Market Status",
"type": "main",
"index": 0
}
]
]
},
"Check Market Status": {
"main": [
[
{
"node": "Check if Market is open",
"type": "main",
"index": 0
}
]
]
},
"Check if Market is open": {
"main": [
[
{
"node": "Ticker List",
"type": "main",
"index": 0
}
],
[
{
"node": "Market is Closed",
"type": "main",
"index": 0
}
]
]
},
"Send Summary to User(s)": {
"main": [
[
{
"node": "End of Flow",
"type": "main",
"index": 0
}
]
]
},
"Stock Analysis Assistant": {
"main": [
[
{
"node": "Send Summary to User(s)",
"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.
httpCustomAuthopenAiApislackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
An automated n8n workflow that analyzes stocks using RSI and MACD, summarizes insights with OpenAI, and sends a Slack-ready market update every hour.
Source: https://n8n.io/workflows/4867/ — 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.
Unleash the full potential of your website's search engine performance and user experience with this all-in-one n8n automation template. Designed for SEO professionals and webmasters, this suite provi
This workflow uses OpenAI Assistant to compose draft replies for labeled email messages. It automatically connects the drafts to Gmail threads.
n8n workflow template description [template] This workflow automatically drafts replies to your emails using an OpenAI Assistant, streamlining your inbox management. It's designed for support teams, s
Categories: AI, Productivity, Career
Hourly Email Summary: This agent scans your inbox every 4 hour and summarizes new emails into a clean, actionable Slack message. Powered by GPT-4, it classifies emails by Urgency (High, Medium, Low) a