Flujo de trabajo para la detección de anomalías en precios de acciones y notificación automática de noticias relacionadas

Avanzado

Este es unCrypto Trading, Multimodal AIflujo de automatización del dominio deautomatización que contiene 26 nodos.Utiliza principalmente nodos como If, Set, Code, DeepL, Merge. Detectar anomalías en el precio de acciones y enviar alertas de noticias usando Marketstack, HackerNews y DeepL

Requisitos previos
  • Bot Token de Slack o URL de Webhook
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "72lks0Gu4Zqi4t0i",
  "meta": {
    "instanceId": "15d6057a37b8367f33882dd60593ee5f6cc0c59310ff1dc66b626d726083b48d",
    "templateCredsSetupCompleted": true
  },
  "name": "Stock Price Anomaly Detection and Related News Automatic Notification Workflow",
  "tags": [],
  "nodes": [
    {
      "id": "a69b05fc-16c6-4f68-bd14-717b647ad900",
      "name": "Verificación Diaria",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -544,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            },
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "7ab68dfb-380e-4880-a948-89ad068e7533",
      "name": "Obtener Datos de Acciones",
      "type": "n8n-nodes-base.marketstack",
      "position": [
        -320,
        0
      ],
      "parameters": {
        "filters": {
          "dateTo": "2025-09-30T00:00:00",
          "latest": false,
          "dateFrom": "2025-09-01T00:00:00"
        },
        "symbols": "AMZN"
      },
      "credentials": {
        "marketstackApi": {
          "id": "fQQ77wILan88cfRN",
          "name": "Marketstack account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e8b1795e-59dd-4c7a-9db0-78d3e3228b25",
      "name": "Calcular Desviación",
      "type": "n8n-nodes-base.code",
      "position": [
        -96,
        0
      ],
      "parameters": {
        "jsCode": "// === パラメータ設定 ===\nconst N = 20;   // 移動平均の期間\nconst k = 2;    // σの倍率(±2σ)\n\n// === データ取得 ===\nlet data = [];\n\n// Marketstackの出力構造をチェック\nif (items[0].json.data) {\n  // 通常ケース(Marketstackノードからそのまま)\n  data = items[0].json.data;\n} else {\n  // 予備パターン:items配列にデータが直接並んでいるケース\n  data = items.map(item => item.json);\n}\n\n// N件だけ抽出\ndata = data.slice(0, N);\n\n// === 終値のみ抽出 ===\nconst closes = data.map(d => d.close).filter(v => typeof v === 'number');\n\n// データがない場合の対策\nif (closes.length === 0) {\n  return [{ json: { error: \"No valid close data found.\" } }];\n}\n\n// === 移動平均と標準偏差を計算 ===\nconst mean = closes.reduce((a, b) => a + b, 0) / closes.length;\nconst variance = closes.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / closes.length;\nconst sigma = Math.sqrt(variance);\n\n// === 最新値(先頭) ===\nconst latestClose = closes[0] + 100;\n\n// === 判定 ===\nlet status = \"normal\";\nif (latestClose > mean + k * sigma) {\n  status = \"high (above +2σ)\";\n} else if (latestClose < mean - k * sigma) {\n  status = \"low (below -2σ)\";\n}\n\n// === 出力 ===\nreturn [\n  {\n    json: {\n      mean: mean.toFixed(2),\n      sigma: sigma.toFixed(2),\n      upper: (mean + k * sigma).toFixed(2),\n      lower: (mean - k * sigma).toFixed(2),\n      latest: latestClose.toFixed(2),\n      status,\n      count: closes.length\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5f5c9951-f936-495d-985f-7ae2108d2787",
      "name": "¿Es Anomalía? (status != \"normal\")",
      "type": "n8n-nodes-base.if",
      "position": [
        128,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f79f5888-e19f-4273-81b7-5b6f434fea65",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{$json[\"status\"]}}",
              "rightValue": "=normal"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "830c1c3b-92d7-42c2-a698-ec213787ace9",
      "name": "Obtener Noticias Relacionadas",
      "type": "n8n-nodes-base.hackerNews",
      "position": [
        800,
        96
      ],
      "parameters": {
        "resource": "all",
        "additionalFields": {
          "keyword": "={{ $json.keyword }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "31e2ca1d-9c30-4dbc-9a67-54e12ca974a3",
      "name": "Traducir Noticias",
      "type": "n8n-nodes-base.deepL",
      "position": [
        1248,
        32
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "translateTo": "JA",
        "additionalFields": {}
      },
      "credentials": {
        "deepLApi": {
          "id": "S5c8ArKkbeIQQU5Z",
          "name": "DeepL account 3"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "478fdb62-dde4-40e3-9e0b-2676330f91c0",
      "name": "Enviar Alerta a Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1696,
        96
      ],
      "webhookId": "e0a002a8-b1df-41ff-a431-459120a37e77",
      "parameters": {
        "text": "=🌐 *Original (English)*  \n{{ $json.message }}\n\n---\n\n🇯🇵 *Translated (Japanese)*  \n{{ $json.text }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "CKUCBTG0H",
          "cachedResultName": "general"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "2kyw7TSL5VT4S3md",
          "name": "Slack account 8"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "7ea2b37e-e074-400d-9e3b-28ac0bc9c816",
      "name": "Enviar Reporte Normal a Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        352,
        -96
      ],
      "webhookId": "b0f44cfc-ae30-4339-9428-c4fb468f900e",
      "parameters": {
        "text": "=✅ 異常なし この銘柄の終値は安定しています。 現在値:{{ $('Calculate Deviation').item.json.latest }}(平均 {{ $('Calculate Deviation').item.json.mean }} ± {{ $('Calculate Deviation').item.json.sigma }})",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "CKUCBTG0H",
          "cachedResultName": "general"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "2kyw7TSL5VT4S3md",
          "name": "Slack account 8"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "34c1613d-306b-47fa-b982-db156c54e053",
      "name": "Combinar Original + Traducido",
      "type": "n8n-nodes-base.merge",
      "position": [
        1472,
        96
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "be7b89c0-99ac-44cb-aec0-03b844bc50f5",
      "name": "Nota Adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -640,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 224,
        "height": 192,
        "content": "## Daily Check (09:00 JST)\n\nStarts the workflow every morning at 09:00 JST. Adjust schedule/timezone as needed."
      },
      "typeVersion": 1
    },
    {
      "id": "2ea66681-b507-4737-a6f4-0d0c2590646f",
      "name": "Nota Adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -400,
        208
      ],
      "parameters": {
        "color": 7,
        "height": 192,
        "content": "## Get Stock Data (Marketstack)\nRetrieves the latest EOD prices for the configured ticker. Edit symbol and date range. Keep the limit ≥ 20 for a stable mean/σ."
      },
      "typeVersion": 1
    },
    {
      "id": "e85baa53-b0ed-4017-98b0-e7a07a88c7aa",
      "name": "Nota Adhesiva2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        304
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 256,
        "content": "## Customization Tips\n\n- Monitor multiple tickers: duplicate **Get Stock Data** and merge results.\n- Replace Hacker News with **NewsAPI** / **Google News RSS** for broader coverage.\n- Switch Slack to **Telegram / Discord / Teams / LINE Messaging API**.\n- Add a **Set (Fields)** node to centralize user-configurable variables:\n  - `symbol` (ticker), `days` (N), `sigmaK` (k), `newsQuery`, `slackChannel`\n- Add an **IF** to translate only when language != JA (cost optimization).\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "22cad535-6c1f-44c1-9018-910baa276cba",
      "name": "Nota Adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -112,
        496
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 384,
        "content": "## Node Structure Overview\n\nFlow:\n🕘 Daily Check (09:00) \n → 📊 Get Stock Data (Marketstack)\n → 🧮 Calculate Deviation (±2σ)\n → 🔀 IF: Is Anomaly? (status != \"normal\")\n\nTrue (Anomaly):\n  → 📰 Get Related News (Hacker News)\n  → ✍️ Format News (Title + Summary + URL)\n  → 🌐 Translate News (EN → JA, DeepL)\n  → 🔗 Merge Original + Translated\n  → 💬 Send Alert to Slack\n\nFalse (Normal):\n  → 💬 Send Normal Report to Slack\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fa231074-0537-4cc6-b33c-e90006605377",
      "name": "Nota Adhesiva4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        352
      ],
      "parameters": {
        "color": 7,
        "height": 176,
        "content": "## Send Normal Report to Slack\n\nSends a concise “no anomaly” message with basic stats.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2c8bbc35-0320-4350-b64f-e58eacd7c974",
      "name": "Nota Adhesiva5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -448
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 272,
        "content": "## 🛠️ Setup Instructions\n\n1. Connect your **Marketstack**, **DeepL**, and **Slack** credentials.\n2. Update ticker symbol inside “Get Stock Data”.\n3. Customize Slack channel in both Slack nodes.\n4. Modify time or schedule in “Daily Check” as needed.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7fbb2805-1ffd-4ce6-86a6-04d9ba827191",
      "name": "Nota Adhesiva6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1184,
        -288
      ],
      "parameters": {
        "width": 480,
        "height": 816,
        "content": "## Price Anomaly Detection & News Alert (Marketstack + HN + DeepL + Slack)\n\n## Overview\nThis workflow monitors a stock’s closing price via **Marketstack**. It computes a **20-day moving average** and **standard deviation (±2σ)**. If the latest close is outside ±2σ, it flags an **anomaly**, fetches **related headlines from Hacker News**, **translates** them to Japanese with **DeepL**, and **posts both original and translated text to Slack**. When no anomaly is detected, it sends a concise “normal” report.\n\n## How it works\n1) Daily trigger at 09:00 JST  \n2) Marketstack: fetch EOD data  \n3) Code: compute mean/σ and classify (normal/high/low)  \n4) IF: anomaly? → yes = news path / no = normal report  \n5) Hacker News: search related items  \n6) DeepL: translate EN → JA  \n7) Slack: send bilingual notification\n\n## Requirements\n- Marketstack API key\n- DeepL API key\n- Slack OAuth2 (bot token / channel permission)\n\n## Notes\n- Edit the ticker in **Get Stock Data**.\n- Adjust **N** (days) and **k** (sigma multiplier) in **Calculate Deviation**.\n- Keep credentials out of HTTP nodes (use n8n Credentials).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4a60a88c-3f9d-4919-9f8e-769138eebad2",
      "name": "Nota Adhesiva7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "content": "## Calculate Deviation\n\nComputes 20-day mean and standard deviation; classifies the latest close as normal, high (+2σ), or low (−2σ)."
      },
      "typeVersion": 1
    },
    {
      "id": "d3e597a0-0400-400d-970d-f179bf3c574c",
      "name": "Nota Adhesiva8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        176
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 176,
        "content": "## Is Anomaly? (status != \"normal\")\n\nBranches to the news path only when the latest close exceeds ±2σ."
      },
      "typeVersion": 1
    },
    {
      "id": "cb2c48c9-349d-4c3e-9f17-ed4636ca0b82",
      "name": "Nota Adhesiva9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 176,
        "content": "## Get Related News (Hacker News)\n\nSearches articles by the ticker/company keyword. You can switch to NewsAPI/Google RSS."
      },
      "typeVersion": 1
    },
    {
      "id": "8a824d8c-3d66-4838-9c5e-a8708afcfa1d",
      "name": "Nota Adhesiva10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        944,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 176,
        "content": "## Format News (Title + Summary + URL)\n\nCleans HTML (e.g., <em>) and formats top items for translation/Slack."
      },
      "typeVersion": 1
    },
    {
      "id": "1ef7949a-e396-449a-b21c-4e72e7031c38",
      "name": "Nota Adhesiva11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 176,
        "content": "## Translate News (EN → JA)\n\nDeepL translation to Japanese. Change target_lang if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "4a410b17-9763-4723-a5f2-61fb6ab50fd7",
      "name": "Nota Adhesiva12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1504,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 176,
        "content": "## Merge Original + Translated\n\nAppends original English and translated Japanese into one message payload."
      },
      "typeVersion": 1
    },
    {
      "id": "0d5d6b48-6983-4136-80e3-0cf9de926972",
      "name": "Nota Adhesiva13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1744,
        -208
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 176,
        "content": "## Send Alert to Slack (Anomaly)\n\nSends bilingual alert with stats (latest, mean, σ) and related news."
      },
      "typeVersion": 1
    },
    {
      "id": "fe474a5c-9358-4f1b-ad07-b2ae6169c280",
      "name": "Agregar Campo Símbolo",
      "type": "n8n-nodes-base.set",
      "position": [
        352,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1de4889-f506-46c6-8189-4e173dad6c39",
              "name": "symbol",
              "type": "string",
              "value": "={{$item(0).$node[\"Get Stock Data\"].json[\"symbol\"]}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ad957b08-b108-427e-9843-b48be879cb3b",
      "name": "Componer Mensaje Slack",
      "type": "n8n-nodes-base.code",
      "position": [
        1024,
        96
      ],
      "parameters": {
        "jsCode": "// === Hacker News 出力からタイトル・本文・URLを整形 ===\nconst results = items.map(item => {\n  const highlight = item.json._highlightResult || {};\n\n  const title =\n    highlight.title?.value ||\n    item.json.title ||\n    \"No Title\";\n\n  const story =\n    highlight.story_text?.value ||\n    item.json.story_text ||\n    \"No summary available.\";\n\n  const url =\n    item.json.url ||\n    highlight.url?.value ||\n    \"No URL\";\n\n  // === HTMLタグ(<em>など)を除去 ===\n  const cleanTitle = title.replace(/<[^>]*>/g, \"\");\n  const cleanStory = story.replace(/<[^>]*>/g, \"\");\n\n  return `📰 ${cleanTitle}\\n${cleanStory}\\n🔗 ${url}`;\n});\n\n// === 出力 ===\nreturn [\n  {\n    json: {\n      message: results.slice(0, 3).join(\"\\n\\n---\\n\\n\"), // 上位3件を区切って結合\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a5ecf56c-8e7d-42da-9335-a2b1a08b71a1",
      "name": "Construir Palabra Clave de Noticias",
      "type": "n8n-nodes-base.code",
      "position": [
        576,
        96
      ],
      "parameters": {
        "jsCode": "const map = {\n  AMZN: 'Amazon',\n  AAPL: 'Apple',\n  GOOG: 'Google',\n  MSFT: 'Microsoft',\n  TSLA: 'Tesla',\n};\n\n// 入力の中身を確認\nconsole.log('INPUT items:', items);\n\nconst first = (items && items[0] && items[0].json) ? items[0].json : {};\nconst symbol = String(first.symbol || first.ticker || '').toUpperCase();\n\nif (!symbol) {\n  // symbolが無い時は理由と入力を返して可視化\n  return [\n    {\n      json: {\n        error: 'symbol is missing',\n        debugInput: first,\n      },\n    },\n  ];\n}\n\nconst keyword = map[symbol] || symbol;\n\nreturn [\n  {\n    json: { keyword, symbol },\n  },\n];\n"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "e90eb5a4-58e8-4a2d-82c3-30862bc8832f",
  "connections": {
    "a69b05fc-16c6-4f68-bd14-717b647ad900": {
      "main": [
        [
          {
            "node": "7ab68dfb-380e-4880-a948-89ad068e7533",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7ab68dfb-380e-4880-a948-89ad068e7533": {
      "main": [
        [
          {
            "node": "e8b1795e-59dd-4c7a-9db0-78d3e3228b25",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "31e2ca1d-9c30-4dbc-9a67-54e12ca974a3": {
      "main": [
        [
          {
            "node": "34c1613d-306b-47fa-b982-db156c54e053",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fe474a5c-9358-4f1b-ad07-b2ae6169c280": {
      "main": [
        [
          {
            "node": "a5ecf56c-8e7d-42da-9335-a2b1a08b71a1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "830c1c3b-92d7-42c2-a698-ec213787ace9": {
      "main": [
        [
          {
            "node": "ad957b08-b108-427e-9843-b48be879cb3b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a5ecf56c-8e7d-42da-9335-a2b1a08b71a1": {
      "main": [
        [
          {
            "node": "830c1c3b-92d7-42c2-a698-ec213787ace9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e8b1795e-59dd-4c7a-9db0-78d3e3228b25": {
      "main": [
        [
          {
            "node": "5f5c9951-f936-495d-985f-7ae2108d2787",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "478fdb62-dde4-40e3-9e0b-2676330f91c0": {
      "main": [
        []
      ]
    },
    "ad957b08-b108-427e-9843-b48be879cb3b": {
      "main": [
        [
          {
            "node": "31e2ca1d-9c30-4dbc-9a67-54e12ca974a3",
            "type": "main",
            "index": 0
          },
          {
            "node": "34c1613d-306b-47fa-b982-db156c54e053",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "34c1613d-306b-47fa-b982-db156c54e053": {
      "main": [
        [
          {
            "node": "478fdb62-dde4-40e3-9e0b-2676330f91c0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5f5c9951-f936-495d-985f-7ae2108d2787": {
      "main": [
        [
          {
            "node": "fe474a5c-9358-4f1b-ad07-b2ae6169c280",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "7ea2b37e-e074-400d-9e3b-28ac0bc9c816",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Comercio de criptomonedas, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos26
Categoría2
Tipos de nodos10
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34