AutomationFlowsData & Sheets › Predict Next 5-day Stock Trends with Twelve Data API & Google Sheets

Predict Next 5-day Stock Trends with Twelve Data API & Google Sheets

ByOneclick AI Squad @oneclick-ai on n8n.io

This automated n8n workflow fetches stock data from the Twelve Data API after market close, predicts 5-day trends using AI analysis, updates Google Sheets with the results, and sends an email summary report. This process helps users stay informed about stock movements and make…

Cron / scheduled trigger★★★★☆ complexity14 nodesGoogle SheetsHTTP RequestEmail Send
Data & Sheets Trigger: Cron / scheduled Nodes: 14 Complexity: ★★★★☆ Added:

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

This workflow follows the Emailsend → Google Sheets 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
{
  "id": "50mjsFfAXxLpbQ3w",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Predict Next 5-Day Stock Trends with Twelve Data API",
  "tags": [],
  "nodes": [
    {
      "id": "6c2c2e16-b520-4af8-864a-3081f53dc594",
      "name": "Daily Market Close Trigger\t",
      "type": "n8n-nodes-base.cron",
      "position": [
        16,
        144
      ],
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "hour": 21
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6dc56381-e0a4-498d-a98c-abf7545e862f",
      "name": "Read Stock Symbols\t",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        240,
        144
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "=1649252791"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "=1eO0pcfO3SFEofhUXjRy8Ps_XqfNpVnu5W8fwVSAy4Ds"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "7cd655b6-edbf-4afd-84af-5465868ce748",
      "name": "Set Configuration Variables\t",
      "type": "n8n-nodes-base.set",
      "position": [
        464,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "api-key-assignment",
              "name": "twelvedata_api_key",
              "type": "string",
              "value": "=YOUR_ACTUAL_API_KEY"
            },
            {
              "id": "symbols-assignment",
              "name": "stock_symbols",
              "type": "string",
              "value": "={{ $json.symbol }}"
            },
            {
              "id": "email-recipient",
              "name": "email_recipient",
              "type": "string",
              "value": "{{ YOUR_ACTUAL_EMAIL_ADDRESS }}"
            },
            {
              "id": "a5906884-6805-4e0a-bcad-21fe4ff7864c",
              "name": "",
              "type": "string",
              "value": ""
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c0ced112-9d1d-4714-88f6-c08e2b5be76d",
      "name": "Fetch 5-Day Stock Data\t",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        688,
        144
      ],
      "parameters": {
        "url": "=https://api.twelvedata.com/time_series?symbol={{ $json.stock_symbols }}&interval=1day&outputsize=5&apikey={{ $json.twelvedata_api_key }}",
        "options": {
          "timeout": 30000
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ce8941d6-5974-49c2-8b83-2442ba9e7ee3",
      "name": "Analyze Stock Trends\t",
      "type": "n8n-nodes-base.code",
      "position": [
        912,
        144
      ],
      "parameters": {
        "jsCode": "// Process 5-day stock data and predict trends\nconst stockData = $input.first().json;\nlet processedStocks = [];\n\n// Check for API error\nif (stockData.error) {\n  throw new Error(`Twelve Data API Error: ${stockData.error.message}`);\n}\n\n// Handle multiple stock responses (array of stock objects)\nconst quotes = Array.isArray(stockData) ? stockData : [stockData];\n\nfor (let stock of quotes) {\n  if (stock && stock.meta && stock.values && Array.isArray(stock.values)) {\n    const symbol = stock.meta.symbol;\n    const currency = stock.meta.currency || stock.meta.currency_quote || 'USD';\n    const prices = stock.values.map(v => parseFloat(v.close)).filter(p => !isNaN(p));\n    \n    // Calculate 5-day trend (simple moving average slope)\n    const trendSlope = prices.length >= 2 ? (prices[0] - prices[prices.length - 1]) / prices.length : 0;\n    const avgPrice = prices.length > 0 ? prices.reduce((sum, p) => sum + p, 0) / prices.length : 0;\n    const predictedChange = trendSlope * 5; // Extrapolate for next 5 days\n    const prediction = predictedChange > 0 ? 'Up' : predictedChange < 0 ? 'Down' : 'Neutral';\n    const absPredictedChange = Math.abs(predictedChange);\n    \n    processedStocks.push({\n      symbol: symbol,\n      name: stock.meta.currency_base || stock.meta.symbol,\n      currency: currency,\n      five_day_data: stock.values.map(v => ({\n        date: v.datetime,\n        close: parseFloat(v.close) || null,\n        high: parseFloat(v.high) || null,\n        low: parseFloat(v.low) || null,\n        volume: parseInt(v.volume) || null\n      })),\n      avg_price: avgPrice.toFixed(2),\n      predicted_trend: prediction,\n      predicted_change: absPredictedChange.toFixed(2),\n      percent_change: prices.length >= 2 ? ((prices[0] - prices[prices.length - 1]) / prices[prices.length - 1] * 100).toFixed(2) : '0.00'\n    });\n  }\n}\n\nconst currentDate = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n\nreturn [{\n  json: {\n    date: currentDate,\n    total_stocks: processedStocks.length,\n    stock_analysis: processedStocks\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "a1c27b1a-ccb7-46c6-8cc3-6c7d043db17f",
      "name": "Update Google Sheet\t",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1136,
        64
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "=juy6t543wsadv"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "=asdfvsdfcdsasdfv"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "d7bc71d1-d405-4ef2-8ac3-ebb12697d705",
      "name": "Format Email Report\t",
      "type": "n8n-nodes-base.code",
      "position": [
        1136,
        224
      ],
      "parameters": {
        "jsCode": "// Generate HTML Email content\nconst data = $input.first().json;\nlet htmlContent = `<!DOCTYPE html><html><head><style>body { font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }.container { max-width: 600px; margin: 0 auto; background: white; padding: 20px; border-radius: 10px; }.header { text-align: center; border-bottom: 2px solid #007bff; padding-bottom: 10px; }.section { margin-bottom: 20px; }.stock-table { width: 100%; border-collapse: collapse; }.stock-table th, .stock-table td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }.stock-table th { background-color: #f8f9fa; }.gain { color: #28a745; }.loss { color: #dc3545; }.symbol { font-weight: bold; color: #007bff; }</style></head><body><div class=\"container\"><div class=\"header\"><h2>\ud83d\udcc8 Stock Trend Analysis Report</h2><p><strong>Date:</strong> ${data.date}</p></div><div class=\"section\"><h3>Stock Analysis (Last 5 Days & Predictions)</h3><table class=\"stock-table\"><thead><tr><th>Symbol</th><th>Avg Price</th><th>5-Day % Change</th><th>Predicted Trend</th><th>Predicted Change ($)</th></tr></thead><tbody>`;\ndata.stock_analysis.forEach(stock => {\n  htmlContent += `<tr><td class=\"symbol\">${stock.symbol}</td><td>$${stock.avg_price}</td><td class=\"${stock.percent_change > 0 ? 'gain' : 'loss'}\">${stock.percent_change}%</td><td>${stock.predicted_trend}</td><td>$${stock.predicted_change}</td></tr>`;\n});\nhtmlContent += `</tbody></table></div><div style=\"text-align: center; margin-top: 20px; color: #666;\"><p>\u26a1 Generated by Stock Trend Predictor</p><p><small>Data provided by Twelve Data API</small></p></div></body></html>`;\nconst plainText = `STOCK TREND ANALYSIS REPORT\\nDate: ${data.date}\\nStocks Analyzed: ${data.total_stocks}\\n\\nSTOCK ANALYSIS:\\n${data.stock_analysis.map((stock, i) => `${i+1}. ${stock.symbol}: Avg $${stock.avg_price}, 5-Day Change: ${stock.percent_change}%, Predicted Trend: ${stock.predicted_trend} ($${stock.predicted_change})`).join('\\n')}\\n\\nGenerated by Stock Trend Predictor`;\nreturn [{ json: { email_html: htmlContent, email_text: plainText, email_subject: `Stock Trend Report - ${data.date}` } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "c57230f1-5204-4d8c-9d79-e46d3f4c7663",
      "name": "Send Email Report\t",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1360,
        224
      ],
      "parameters": {
        "html": "={{ $json.email_html }}",
        "options": {},
        "subject": "={{ $json.email_subject }}",
        "toEmail": "=abc@gmail.com",
        "fromEmail": "user@example.com",
        "emailFormat": "html"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "32f22649-c65d-40a0-bf3c-9855dc759090",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 160,
        "height": 300,
        "content": "Triggers daily at 9:00 PM (after market close) Monday-Friday.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4fb6d2c7-a176-4061-ab77-59f3f3cf9346",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        0
      ],
      "parameters": {
        "color": 3,
        "width": 170,
        "height": 300,
        "content": "Reads stock symbols from Google Sheet.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9541a2ed-f97d-4d28-8b34-98bcd51e0155",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        416,
        0
      ],
      "parameters": {
        "color": 4,
        "width": 170,
        "height": 300,
        "content": "Sets API key and stock symbols.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e8055a14-a549-4433-b4cb-c4424eec657b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        0
      ],
      "parameters": {
        "color": 5,
        "width": 170,
        "height": 300,
        "content": "Fetches 5-day stock data from Twelve Data API.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fc86755b-d63c-4546-9147-05356ca4fc9b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        0
      ],
      "parameters": {
        "color": 6,
        "width": 170,
        "height": 300,
        "content": "Analyzes trends and predicts next 5-day movement.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "36bcd40b-c972-4428-86e7-7b1d05e3fe94",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        0
      ],
      "parameters": {
        "color": 2,
        "width": 170,
        "height": 300,
        "content": "Updates Google Sheet and sends email report.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "f7ed1f84-39d4-42f1-b857-bc78d3ee4454",
  "connections": {
    "Read Stock Symbols\t": {
      "main": [
        [
          {
            "node": "Set Configuration Variables\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Email Report\t": {
      "main": [
        [
          {
            "node": "Send Email Report\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze Stock Trends\t": {
      "main": [
        [
          {
            "node": "Update Google Sheet\t",
            "type": "main",
            "index": 0
          },
          {
            "node": "Format Email Report\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch 5-Day Stock Data\t": {
      "main": [
        [
          {
            "node": "Analyze Stock Trends\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Market Close Trigger\t": {
      "main": [
        [
          {
            "node": "Read Stock Symbols\t",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration Variables\t": {
      "main": [
        [
          {
            "node": "Fetch 5-Day Stock Data\t",
            "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.

Pro

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

About this workflow

This automated n8n workflow fetches stock data from the Twelve Data API after market close, predicts 5-day trends using AI analysis, updates Google Sheets with the results, and sends an email summary report. This process helps users stay informed about stock movements and make…

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

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

Security teams, DevOps engineers, vulnerability analysts, and automation builders who want to eliminate repetitive Nessus scan parsing, AI-based risk triage, and manual reporting. Designed for orgs fo

Email Send, HTTP Request, Google Sheets +1
Data & Sheets

This n8n workflow automatically finds apartments for rent in Germany, filters them by your city, rent budget, and number of rooms, and applies to them via email. Each application includes: A personali

HTTP Request, Google Drive, Email Send +1
Data & Sheets

👤 Who it’s for Blue Team leads, CISOs, and SOC managers who want automated visibility into threat metrics, endpoint alerts, and response actions — without needing a full SIEM or BI platform.

HTTP Request, Email Send, Google Sheets
Data & Sheets

Workflow Overview Zoom Attendance Evaluator with Follow-up is an n8n automation workflow that automatically evaluates Zoom meeting attendance and sends follow-up emails to no-shows and early leavers w

Zoom, Item Lists, HTTP Request +3
Data & Sheets

This workflow automatically monitors Amazon product prices, tracks price changes, and sends alerts when significant price fluctuations occur. Built with ScrapeOps' structured data API, it provides a r

Google Sheets, HTTP Request, Email Send