This workflow corresponds to n8n.io template #8094 — 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": "qYCUH4cxGizp7l1b",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Stock Analytic Template",
"tags": [],
"nodes": [
{
"id": "1976d330-4339-4a6c-9915-f62fcb2690be",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"onError": "continueErrorOutput",
"maxTries": 3,
"position": [
768,
-432
],
"parameters": {
"text": "=\u041f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0430\u043a\u0446\u0438\u0438 {{ $json.context.ticker }} \u043d\u0430 \u0442\u0430\u0439\u043c\u0444\u0440\u0435\u0439\u043c\u0435 {{ $json.context.timeFrame }} \u0438 \u0441\u043e\u0437\u0434\u0430\u0439 \u0432\u0438\u0440\u0443\u0441\u043d\u044b\u0439 \u043f\u043e\u0441\u0442 \u0434\u043b\u044f \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439.\n\n\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430:\n{{ JSON.stringify($json, null, 2) }}\n\n\u0421\u043e\u0437\u0434\u0430\u0439 JSON \u0441 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c \u0438 \u043f\u043e\u043b\u043d\u044b\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0430 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c.",
"options": {
"systemMessage": "=\u0420\u043e\u043b\u044c \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\n\u0422\u044b \u2014 \u044d\u043a\u0441\u043f\u0435\u0440\u0442 \u043f\u043e \u0430\u043a\u0446\u0438\u044f\u043c \u0441 10+ \u043b\u0435\u0442 \u043e\u043f\u044b\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0432\u0435\u0449\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438. \u0422\u0432\u043e\u044f \u0430\u0443\u0434\u0438\u0442\u043e\u0440\u0438\u044f \u2014 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043b\u044e\u0434\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u044f\u0442 \u0437\u0430\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0430\u043a\u0446\u0438\u044f\u0445, \u043d\u043e \u043d\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445.\n\n\u0417\u0430\u0434\u0430\u0447\u0430\n\u0421\u043e\u0437\u0434\u0430\u0439 \u0432\u0438\u0440\u0443\u0441\u043d\u044b\u0439 \u043f\u043e\u0441\u0442 \u0434\u043b\u044f \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439:\n- \u041f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0441 \u043f\u0435\u0440\u0432\u044b\u0445 \u0441\u0442\u0440\u043e\u043a\n- \u041e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e \u0431\u0435\u0437 \u0436\u0430\u0440\u0433\u043e\u043d\u0430 \n- \u0414\u0430\u0435\u0442 \u0447\u0435\u0442\u043a\u0438\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438\n- \u041c\u043e\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u0443\u044e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443\n\n\u0424\u043e\u0440\u043c\u0430\u0442 \u043e\u0442\u0432\u0435\u0442\u0430\n\u0412\u0410\u0416\u041d\u041e: \u041e\u0442\u0432\u0435\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0422\u041e\u041b\u042c\u041a\u041e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON:\n{\n \"title\": \"\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043f\u043e\u0441\u0442\u0430\",\n \"summary\": \"\u041f\u043e\u043b\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0441\u0442\u0430\"\n}\n\n\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 title:\n\ud83d\udd25 \u0418\u043d\u0442\u0440\u0438\u0433\u0443\u044e\u0449\u0438\u0439 \u0445\u0443\u043a-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a (1 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u044d\u043c\u043e\u0434\u0437\u0438):\n- \"\ud83d\udd25 \u0413\u0430\u0437\u043f\u0440\u043e\u043c \u0433\u043e\u0442\u043e\u0432\u0438\u0442\u0441\u044f \u043a \u0440\u044b\u0432\u043a\u0443 \u0432\u0432\u0435\u0440\u0445!\"\n- \"\u26a1 \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435! \u0421\u0431\u0435\u0440 \u0434\u0430\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430 \u043f\u043e\u043a\u0443\u043f\u043a\u0443\" \n- \"\ud83c\udfaf \u042f\u043d\u0434\u0435\u043a\u0441: \u0432\u0440\u0435\u043c\u044f \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0438\u043b\u0438 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u0442\u044c?\"\n\n\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 summary (4 \u0431\u043b\u043e\u043a\u0430):\n\n1. \ud83d\udcca \u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u0435\u0439\u0447\u0430\u0441 (2-3 \u0441\u0442\u0440\u043e\u043a\u0438)\n\u041f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043e\u0431\u044a\u044f\u0441\u043d\u0438 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e:\n- \u0420\u0430\u0441\u0442\u0435\u0442/\u043f\u0430\u0434\u0430\u0435\u0442/\u0441\u0442\u043e\u0438\u0442 \u0432 \u0431\u043e\u043a\u043e\u0432\u0438\u043a\u0435\n- \u041f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b\u0438 \u0441\u0438\u043b\u044c\u043d\u0435\u0435/\u0441\u043b\u0430\u0431\u0435\u0435 \u043f\u0440\u043e\u0434\u0430\u0432\u0446\u043e\u0432\n- \u0412\u044b\u0441\u043e\u043a\u0430\u044f/\u043d\u0438\u0437\u043a\u0430\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0442\u043e\u0440\u0433\u043e\u0432\n\n2. \ud83c\udfaf \u0421\u0438\u0433\u043d\u0430\u043b\u044b \u0440\u044b\u043d\u043a\u0430 \u0433\u043e\u0432\u043e\u0440\u044f\u0442 (3-4 \u0441\u0442\u0440\u043e\u043a\u0438)\n\u041f\u0435\u0440\u0435\u0432\u0435\u0434\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043d\u0430 \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a:\n\n\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432:\n- RSI > 70 = \"\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u043a\u0443\u043f\u043b\u0435\u043d\u0430\"\n- RSI < 30 = \"\u0430\u043a\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0434\u0430\u043d\u0430\"\n- RSI 40-60 = \"\u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044c\u043d\u0430\u044f \u0437\u043e\u043d\u0430\"\n- MACD bullish = \"\u0438\u043c\u043f\u0443\u043b\u044c\u0441 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u0438\u043b\u0443\"\n- MACD bearish = \"\u0438\u043c\u043f\u0443\u043b\u044c\u0441 \u0441\u043b\u0430\u0431\u0435\u0435\u0442\"\n- \u0426\u0435\u043d\u0430 \u0432\u044b\u0448\u0435 SMA20 = \"\u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0440\u043e\u0447\u043d\u044b\u0439 \u0442\u0440\u0435\u043d\u0434 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439\"\n- EMA death cross = \"\u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u044b\u0439 \u043c\u0435\u0434\u0432\u0435\u0436\u0438\u0439 \u0441\u0438\u0433\u043d\u0430\u043b\"\n- EMA golden cross = \"\u0434\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u044b\u0439 \u0431\u044b\u0447\u0438\u0439 \u0441\u0438\u0433\u043d\u0430\u043b\"\n- ADX > 25 = \"\u0441\u0438\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0435\u043d\u0434\"\n- ADX < 20 = \"\u0441\u043b\u0430\u0431\u044b\u0439 \u0442\u0440\u0435\u043d\u0434\"\n- BB \u043f\u043e\u0437\u0438\u0446\u0438\u044f > 0.8 = \"\u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u0430\u043d\u0430\u043b\u0430\"\n- BB \u043f\u043e\u0437\u0438\u0446\u0438\u044f < 0.2 = \"\u0432 \u043d\u0438\u0436\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u0430\u043d\u0430\u043b\u0430\"\n\n3. \ud83d\udca1 \u0427\u0442\u043e \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0441 (2-3 \u0441\u0442\u0440\u043e\u043a\u0438)\n\u041e\u0431\u044a\u044f\u0441\u043d\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0438 \u043a \u0447\u0435\u043c\u0443 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438:\n- \u041a\u0430\u043a\u0438\u0435 \u0440\u0438\u0441\u043a\u0438\n- \u041a\u0430\u043a\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\n- \u041d\u0430 \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435\n\n4. \u26a1 \u041f\u043b\u0430\u043d \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 (2-3 \u0441\u0442\u0440\u043e\u043a\u0438 + \u043f\u0440\u0438\u0437\u044b\u0432)\n\u0427\u0435\u0442\u043a\u0438\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438:\n- \u041f\u041e\u041a\u0423\u041f\u0410\u0415\u041c \u2014 \u0435\u0441\u043b\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435\n- \u041f\u0420\u041e\u0414\u0410\u0415\u041c \u2014 \u0435\u0441\u043b\u0438 \u043f\u043e\u0440\u0430 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0431\u044b\u043b\u044c\n- \u0416\u0414\u0415\u041c \u2014 \u0435\u0441\u043b\u0438 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043d\u0435\u044f\u0441\u043d\u0430\u044f\n\n\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u0437\u044b\u0432: \"\u0421\u0442\u0430\u0432\u044c \u2764\ufe0f \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u043e! \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0441\u044f \u043d\u0430 \u0435\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u0443\u044e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443 \ud83d\udcc8\"\n\n\u0421\u0442\u0438\u043b\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f:\n- \u2705 \u041f\u0440\u043e\u0441\u0442\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u0432\n- \u2705 \u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0433\u043b\u0430\u0433\u043e\u043b\u044b \u0438 \u044d\u043c\u043e\u0446\u0438\u0438\n- \u2705 \u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f\n- \u2705 \u0423\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0432 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f\u0445\n- \u2705 \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u043c\u043e\u0434\u0437\u0438 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\n- \u274c \u041d\u0438\u043a\u0430\u043a\u043e\u0439 \u043d\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0441\u0442\u0438 (\"\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\", \"\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c\")\n- \u274c \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0436\u0430\u0440\u0433\u043e\u043d \u0431\u0435\u0437 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0439\n- \u274c \u0414\u043b\u0438\u043d\u043d\u044b\u0435 \u0430\u0431\u0437\u0430\u0446\u044b\n\n\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e JSON:\n- \u0412\u0441\u0435 \u0441\u043f\u0435\u0446\u0441\u0438\u043c\u0432\u043e\u043b\u044b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u044b\n- \u041f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u0441\u0442\u0440\u043e\u043a \u0447\u0435\u0440\u0435\u0437 \\n\n- \u0416\u0438\u0440\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u043a\u0441\u0442\n- *\u041a\u0443\u0440\u0441\u0438\u0432* \u0447\u0435\u0440\u0435\u0437 *\u0442\u0435\u043a\u0441\u0442*\n- \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u043d\u0430 summary: 1200 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432\n\n\u0426\u0435\u043b\u044c:\n\u0427\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c: *\"\u0412\u0430\u0443, \u043a\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u043b! \u0425\u043e\u0447\u0443 \u0435\u0449\u0435 \u0442\u0430\u043a\u0443\u044e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443!\"*\n\n\u041f\u0440\u0438\u043c\u0435\u0440 \u043e\u0442\u0432\u0435\u0442\u0430:\n{\n \"title\": \"\ud83d\udd25 \u0413\u0430\u0437\u043f\u0440\u043e\u043c: \u0433\u043e\u0442\u043e\u0432\u0438\u0442\u0441\u044f \u043c\u043e\u0449\u043d\u044b\u0439 \u0440\u044b\u0432\u043e\u043a \u0432\u0432\u0435\u0440\u0445!\",\n \"summary\": \"\ud83d\udcca \u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u0435\u0439\u0447\u0430\u0441:\\n\u0413\u0430\u0437\u043f\u0440\u043e\u043c \u0442\u043e\u0440\u0433\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u0448\u0435 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438. \u041f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0435\u0435 \u043f\u0440\u043e\u0434\u0430\u0432\u0446\u043e\u0432, \u043e\u0431\u044a\u0435\u043c\u044b \u0442\u043e\u0440\u0433\u043e\u0432 \u0440\u0430\u0441\u0442\u0443\u0442. \u0410\u043a\u0446\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0438 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u0440\u044b\u0432\u043a\u043e\u043c.\\n\\n\ud83c\udfaf \u0421\u0438\u0433\u043d\u0430\u043b\u044b \u0440\u044b\u043d\u043a\u0430 \u0433\u043e\u0432\u043e\u0440\u044f\u0442:\\n\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0438\u043b\u044b \u0432 \u043d\u0435\u0439\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u043e\u043d\u0435 - \u0435\u0441\u0442\u044c \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b \u0434\u043b\u044f \u0440\u043e\u0441\u0442\u0430. \u0418\u043c\u043f\u0443\u043b\u044c\u0441 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u0438\u043b\u0443, \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0440\u043e\u0447\u043d\u044b\u0439 \u0442\u0440\u0435\u043d\u0434 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439. \u0410\u043a\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0442\u043e\u0440\u0433\u043e\u0432\u043e\u0433\u043e \u043a\u0430\u043d\u0430\u043b\u0430, \u0447\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e\u0431 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043a\u0443\u043f\u0430\u0442\u0435\u043b\u0435\u0439.\\n\\n\ud83d\udca1 \u0427\u0442\u043e \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0441:\\n\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f \u0440\u043e\u0441\u0442\u0430. \u0425\u043e\u0440\u043e\u0448\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u044e. \u0420\u0438\u0441\u043a\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u0443\u0440\u043e\u0432\u043d\u044f\u043c\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438.\\n\\n\u26a1 \u041f\u043b\u0430\u043d \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439:\\n\u041f\u041e\u041a\u0423\u041f\u0410\u0415\u041c \u2014 \u0432\u0441\u0435 \u0441\u0438\u0433\u043d\u0430\u043b\u044b \u0437\u0435\u043b\u0435\u043d\u044b\u0435, \u0442\u0440\u0435\u043d\u0434 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u043e\u0441\u0442. \u0426\u0435\u043b\u0435\u0432\u043e\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c 140-145 \u0440\u0443\u0431\u043b\u0435\u0439 \u0437\u0430 \u0430\u043a\u0446\u0438\u044e.\\n\\n\u0421\u0442\u0430\u0432\u044c \u2764\ufe0f \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u043e! \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0441\u044f \u043d\u0430 \u043a\u0430\u043d\u0430\u043b \ud83d\udcc8\"\n}\n\n\u041a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u043e:\n- \u041e\u0442\u0432\u0435\u0442 \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 JSON-\u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u044d\u0442\u043e\u0433\u043e \u0432\u0438\u0434\u0430:\n{\"title\": \"string\", \"summary\": \"string\"}. \n- \u0411\u0435\u0437 \u043a\u043e\u0434\u0430, \u0431\u0435\u0437 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043d\u0435 JSON. \n- \u041f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u0441\u0442\u0440\u043e\u043a \u2014 \\n. \n- \u041a\u0430\u0432\u044b\u0447\u043a\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0442\u0440\u043e\u043a \u2014 \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c.\n- \u041e\u0442\u0432\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0422\u041e\u041b\u042c\u041a\u041e \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439 JSON\n- \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432 \u0432\u043d\u0435 JSON\n- \u0412\u0441\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u044b \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u044f\u0437\u044b\u043a\n- \u0427\u0435\u0442\u043a\u0430\u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f \u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044e \u0432 \u043a\u043e\u043d\u0446\u0435"
},
"promptType": "define",
"hasOutputParser": true
},
"retryOnFail": true,
"typeVersion": 2.2
},
{
"id": "bf94369a-e36d-460e-903e-2c78a428291d",
"name": "OpenRouter Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"position": [
736,
-64
],
"parameters": {
"model": "openai/gpt-oss-120b",
"options": {}
},
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "8affe1e1-06bb-49ab-bead-95e6de0696f8",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-192,
-432
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 11,
"triggerAtMinute": 15
},
{
"triggerAtHour": 18,
"triggerAtMinute": 15
}
]
}
},
"typeVersion": 1.2
},
{
"id": "2843ee64-77b1-40ad-927c-742786ecd60e",
"name": "Execute Auth Login",
"type": "n8n-nodes-base.executeWorkflow",
"position": [
880,
-704
],
"parameters": {
"options": {},
"workflowId": {
"__rl": true,
"mode": "list",
"value": "gz5RhsAPZztWijnP",
"cachedResultName": "BCS Login"
},
"workflowInputs": {
"value": {},
"schema": [
{
"id": "s",
"type": "string",
"display": true,
"required": false,
"displayName": "s",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"s"
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
}
},
"typeVersion": 1.2
},
{
"id": "95946c93-adc2-48e5-b7d8-3413551c694a",
"name": "Execute Auth Trade API",
"type": "n8n-nodes-base.executeWorkflow",
"position": [
208,
-432
],
"parameters": {
"options": {},
"workflowId": {
"__rl": true,
"mode": "list",
"value": "e4nUcFlYhUsQcGi8",
"cachedResultName": "Trade API Auth"
},
"workflowInputs": {
"value": {
"ticker": "={{ $json.ticker }}",
"classCode": "={{ $json.classCode }}"
},
"schema": [
{
"id": "ticker",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ticker",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "classCode",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "classCode",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"s"
],
"attemptToConvertTypes": false,
"convertFieldsToString": true
}
},
"typeVersion": 1.2
},
{
"id": "4555c391-af96-4600-9d27-5df6e60489f0",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-192,
-672
],
"parameters": {
"updates": [
"callback_query"
],
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "86148c42-ccfd-4565-b32c-b9316bc38ee8",
"name": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438",
"type": "n8n-nodes-base.telegram",
"position": [
1248,
-608
],
"parameters": {
"text": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438",
"chatId": "{ admin_chat_id }",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "3475bd7c-edd8-4bc5-9a7c-40c2ca16bff5",
"name": "\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e",
"type": "n8n-nodes-base.telegram",
"position": [
1248,
-768
],
"parameters": {
"text": "\u041f\u043e\u0441\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d",
"chatId": "{ admin_chat_id }",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "b59a7aa8-ec1c-44e2-88ef-dd945631864e",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
864,
-208
],
"parameters": {
"autoFix": true,
"schemaType": "manual",
"inputSchema": "{\n \"title\": \"string\",\n \"summary\": \"string\"\n}"
},
"typeVersion": 1.3
},
{
"id": "e8f8b5c4-f4a3-492d-a78a-ac34261a8b94",
"name": "Get Action Type",
"type": "n8n-nodes-base.set",
"position": [
-16,
-672
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ccf9b9b2-6b12-4bf7-9b35-7f2b70a49e40",
"name": "action",
"type": "string",
"value": "={{ $json.callback_query.data.split('::')[0] }}"
},
{
"id": "52ee0570-ed4c-4d3a-bc79-ed2589db5cae",
"name": "id",
"type": "string",
"value": "={{ $json.callback_query.data.split('::')[1] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "fc7a86db-af8b-4201-a794-7dd60bf5e14e",
"name": "Exist type and id",
"type": "n8n-nodes-base.if",
"position": [
160,
-672
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ca9eaef8-3da9-477c-a782-e7f4f2f7452f",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.action }}",
"rightValue": ""
},
{
"id": "abaf219d-a434-484b-85e6-854f2f78481d",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.id }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "153d877b-6ada-482d-acf9-141cc5e18776",
"name": "Get Post By Id",
"type": "n8n-nodes-base.postgres",
"position": [
352,
-688
],
"parameters": {
"limit": 1,
"table": {
"__rl": true,
"mode": "list",
"value": "analytics_history",
"cachedResultName": "analytics_history"
},
"where": {
"values": [
{
"value": "={{ $json.id }}",
"column": "id"
}
]
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {},
"operation": "select"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.6
},
{
"id": "86b0748f-c556-4979-a69f-9156d6085f2e",
"name": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438",
"type": "n8n-nodes-base.telegram",
"position": [
1184,
-208
],
"parameters": {
"text": "=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u0441\u0442\u0430 ticker: {{ $json.context.ticker }}",
"chatId": "{ admin_chat_id }",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "00861c84-cad2-4822-8378-e37c7d07f5f5",
"name": "\u0418\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435",
"type": "n8n-nodes-base.httpRequest",
"maxTries": 2,
"position": [
400,
-432
],
"parameters": {
"url": "https://be.broker.ru/trade-api-market-data-connector/api/v1/candles-chart",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "ticker",
"value": "={{ $('\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u0443\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f ticker)').item.json.ticker }}"
},
{
"name": "classCode",
"value": "={{ $('\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u0443\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f ticker)').item.json.classCode }}"
},
{
"name": "timeFrame",
"value": "H1"
},
{
"name": "startDate",
"value": "={{new Date(Date.now() - 24 * 60 * 60 * 1000 * 60).toISOString()}}"
},
{
"name": "endDate",
"value": "={{new Date().toISOString()}}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "=Bearer {{ $('Execute Auth Trade API').item.json.access_token }}"
}
]
}
},
"retryOnFail": true,
"typeVersion": 4.1,
"alwaysOutputData": true
},
{
"id": "0258bea4-7914-4fd3-8161-52dc5a1ee4fd",
"name": "\u0420\u0430\u0441\u0441\u0447\u0435\u0442 TA",
"type": "n8n-nodes-base.code",
"position": [
592,
-432
],
"parameters": {
"jsCode": "// ===== Compact TA for multi-ticker =====\n// Input options:\n// A) multiple items: [{ json: { ticker, classCode, timeFrame, bars: [...] } }, ...]\n// B) single item with batch: { json: { batch: [{ticker, classCode, timeFrame, bars:[...]}] } }\n// C) single item with dict: { json: { barsByTicker: { TICKER: [...], ... }, classCode, timeFrame } }\n//\n// Output: one item per ticker: { context, last, derived }\n\nconst PERIOD_RSI = 14;\nconst BB_PERIOD = 20, BB_K = 2.0;\nconst SMA_PERIOD = 20;\nconst EMA_FAST = 50, EMA_SLOW = 200;\nconst MACD_FAST = 12, MACD_SLOW = 26, MACD_SIGNAL = 9;\nconst ADX_PERIOD = 14;\n\n// ---------- helpers ----------\nfunction num(x){ const n = Number(x); return Number.isFinite(n) ? n : NaN; }\nfunction sma(arr, p){\n const out = new Array(arr.length).fill(null); let s=0;\n for(let i=0;i<arr.length;i++){ s+=arr[i]; if(i>=p) s-=arr[i-p]; if(i>=p-1) out[i]=s/p; }\n return out;\n}\nfunction ema(arr, p){\n const out=new Array(arr.length).fill(null); const k=2/(p+1);\n let s=0; for(let i=0;i<p;i++) s+=arr[i]; let prev=s/p; out[p-1]=prev;\n for(let i=p;i<arr.length;i++){ prev=arr[i]*k + prev*(1-k); out[i]=prev; }\n return out;\n}\nfunction rollingStd(arr,p){\n const out=new Array(arr.length).fill(null);\n for(let i=p-1;i<arr.length;i++){\n const sl=arr.slice(i-p+1,i+1);\n const m=sl.reduce((a,b)=>a+b,0)/sl.length;\n const v=sl.reduce((a,b)=>a+(b-m)*(b-m),0)/sl.length;\n out[i]=Math.sqrt(v);\n }\n return out;\n}\nfunction rsi(arr,p=14){\n const out=new Array(arr.length).fill(null); let g=0,l=0;\n for(let i=1;i<=p;i++){ const ch=arr[i]-arr[i-1]; if(ch>0) g+=ch; else l-=ch; }\n let avgG=g/p, avgL=l/p; out[p]=100 - (100/(1 + (avgL===0?Infinity:avgG/avgL)));\n for(let i=p+1;i<arr.length;i++){\n const ch=arr[i]-arr[i-1], gain=Math.max(ch,0), loss=Math.max(-ch,0);\n avgG=(avgG*(p-1)+gain)/p; avgL=(avgL*(p-1)+loss)/p;\n out[i]=100 - (100/(1 + (avgL===0?Infinity:avgG/avgL)));\n }\n return out;\n}\nfunction wilder(arr,p){\n const out=new Array(arr.length).fill(null); let s=0;\n for(let i=0;i<p;i++) s+=arr[i]||0; let prev=s/p; out[p-1]=prev; const a=1/p;\n for(let i=p;i<arr.length;i++){ prev=prev + a*((arr[i]||0)-prev); out[i]=prev; }\n return out;\n}\nfunction tr(h,l,pc){ return Math.max(h-l, Math.abs(h-pc), Math.abs(l-pc)); }\nfunction adx(highs,lows,closes,p=14){\n const len=closes.length, TR=new Array(len).fill(null), plusDM=new Array(len).fill(null), minusDM=new Array(len).fill(null);\n for(let i=1;i<len;i++){\n const up=highs[i]-highs[i-1], dn=lows[i-1]-lows[i];\n plusDM[i]=(up>dn && up>0)?up:0; minusDM[i]=(dn>up && dn>0)?dn:0; TR[i]=tr(highs[i],lows[i],closes[i-1]);\n }\n const ATR=wilder(TR.map(v=>v??0),p);\n const plusDI=wilder(plusDM.map(v=>v??0),p).map((v,i)=> ATR[i]?100*v/ATR[i]:null);\n const minusDI=wilder(minusDM.map(v=>v??0),p).map((v,i)=> ATR[i]?100*v/ATR[i]:null);\n const DX=plusDI.map((pdi,i)=> (pdi!=null && minusDI[i]!=null && (pdi+minusDI[i])!==0)? 100*Math.abs(pdi-minusDI[i])/(pdi+minusDI[i]) : null);\n const ADX=wilder(DX.map(v=>v??0),p);\n return { plusDI, minusDI, ADX };\n}\nfunction clamp01(x){ return Math.max(0, Math.min(1, x)); }\n\n// ---------- core compute for single ticker ----------\nfunction computeOne(meta){\n const raw = Array.isArray(meta.bars) ? meta.bars : [];\n if (raw.length < 30) {\n return {\n error: true,\n payload: { context: { ticker: meta.ticker ?? null }, message: \"\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0430\u0440\u043e\u0432 (\u043d\u0443\u0436\u043d\u043e >= 30)\" }\n };\n }\n\n // sort asc & normalize\n const bars = raw.slice().sort((a,b)=> new Date(a.time) - new Date(b.time))\n .map(b=>({\n time:String(b.time),\n open:num(b.open), high:num(b.high), low:num(b.low), close:num(b.close), volume:num(b.volume)\n }));\n\n const N = bars.length;\n const closes = bars.map(b=>b.close), highs = bars.map(b=>b.high), lows = bars.map(b=>b.low);\n\n // series\n const rsi14 = rsi(closes, PERIOD_RSI);\n const sma20 = sma(closes, SMA_PERIOD);\n const ema50 = ema(closes, EMA_FAST);\n const ema200 = ema(closes, EMA_SLOW);\n\n const ema12 = ema(closes, MACD_FAST);\n const ema26 = ema(closes, MACD_SLOW);\n const macdLine = closes.map((_,i)=> (ema12[i]!=null && ema26[i]!=null) ? ema12[i]-ema26[i] : null);\n const macdForSignal = macdLine.map(v=> v==null ? 0 : v);\n const macdSignalCore = ema(macdForSignal.filter((_,i)=> macdLine[i]!=null), MACD_SIGNAL);\n let si=0; const macdSignal = macdLine.map(v=> v!=null ? macdSignalCore[si++] : null);\n const macdHist = macdLine.map((v,i)=> (v!=null && macdSignal[i]!=null) ? v - macdSignal[i] : null);\n\n const bbMid = sma20;\n const bbStd = rollingStd(closes, BB_PERIOD);\n const bbUpper = bbMid.map((m,i)=> m!=null ? m + BB_K*bbStd[i] : null);\n const bbLower = bbMid.map((m,i)=> m!=null ? m - BB_K*bbStd[i] : null);\n\n const { plusDI, minusDI, ADX } = adx(highs, lows, closes, ADX_PERIOD);\n\n // last\n const i = N - 1;\n const price = closes[i];\n const last = {\n price,\n rsi14: rsi14[i],\n macd: macdLine[i],\n macdSignal: macdSignal[i],\n macdHist: macdHist[i],\n bbUpper: bbUpper[i],\n bbMid: bbMid[i],\n bbLower: bbLower[i],\n sma20: sma20[i],\n ema50: ema50[i],\n ema200: ema200[i],\n adx14: ADX[i],\n plusDI: plusDI[i],\n minusDI: minusDI[i],\n };\n\n const derived = {\n priceAboveSma20: (price!=null && last.sma20!=null) ? (price > last.sma20) : null,\n emaCross: (last.ema50!=null && last.ema200!=null) ? (last.ema50>last.ema200 ? \"golden\" : last.ema50<last.ema200 ? \"death\" : \"flat\") : null,\n macdBias: (last.macd!=null && last.macdSignal!=null) ? (last.macd > last.macdSignal ? \"bullish\" : \"bearish\") : null,\n trendStrength: (last.adx14==null) ? null : (last.adx14<20 ? \"weak\" : last.adx14<40 ? \"moderate\" : \"strong\"),\n bbPos01: (last.bbUpper!=null && last.bbLower!=null && price!=null) ? clamp01((price - last.bbLower) / (last.bbUpper - last.bbLower)) : null,\n };\n\n const context = {\n ticker: meta.ticker ?? null,\n classCode: meta.classCode ?? null,\n timeFrame: meta.timeFrame ?? \"H1\",\n end: bars[N-1].time\n };\n\n return { error:false, payload:{ context, last, derived } };\n}\n\n// ---------- gather inputs ----------\nconst inputs = $input.all(); // A) multiple items case\n\nlet jobs = [];\n\n// A) multiple items with per-ticker bars\nif (inputs.length > 1 || (inputs[0]?.json?.bars && inputs[0]?.json?.ticker)) {\n jobs = inputs.map(it => ({ ticker: it.json.ticker, meta: it.json }));\n}\n// B) single item with batch: meta.batch = [{ticker, bars, ...}, ...]\nelse if (Array.isArray(inputs[0]?.json?.batch)) {\n jobs = inputs[0].json.batch.map(x => ({ ticker: x.ticker, meta: x }));\n}\n// C) single item with dict: meta.barsByTicker = { TICK1:[...], TICK2:[...] }\nelse if (inputs[0]?.json?.barsByTicker && typeof inputs[0].json.barsByTicker === 'object') {\n const common = { classCode: inputs[0].json.classCode, timeFrame: inputs[0].json.timeFrame };\n jobs = Object.entries(inputs[0].json.barsByTicker).map(([ticker, bars]) => ({\n ticker,\n meta: { ...common, ticker, bars }\n }));\n}\n// fallback: single standard item\nelse {\n jobs = [{ ticker: inputs[0]?.json?.ticker ?? null, meta: inputs[0]?.json ?? {} }];\n}\n\n// ---------- compute and return one item per ticker ----------\nconst out = [];\nfor (const { meta } of jobs) {\n const res = computeOne(meta);\n if (res.error) {\n out.push({ json: { error: res.payload.message || \"\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u0430\u0440\u043e\u0432 (\u043d\u0443\u0436\u043d\u043e >= 30)\", context: { ticker: meta.ticker ?? null } } });\n } else {\n out.push({ json: res.payload });\n }\n}\n\nreturn out;\n"
},
"typeVersion": 2
},
{
"id": "f721ec3f-c629-4045-b80d-786e78fc6672",
"name": "ID Generation",
"type": "n8n-nodes-base.crypto",
"position": [
1072,
-432
],
"parameters": {
"action": "generate"
},
"typeVersion": 1
},
{
"id": "a5271f93-d5da-4e12-832d-de52d5c96dbe",
"name": "\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0441\u0442\u0430 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e",
"type": "n8n-nodes-base.telegram",
"onError": "continueErrorOutput",
"position": [
1424,
-432
],
"parameters": {
"text": "={{ $json.title }}\n\n{{ $json.summary }}",
"chatId": "={ admin_chat_id }",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c",
"additionalFields": {
"callback_data": "=publish::{{ $('ID Generation').item.json.data }}"
}
},
{
"text": "\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c",
"additionalFields": {
"callback_data": "=retry::{{ $('ID Generation').item.json.data }}"
}
}
]
}
}
]
},
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"executeOnce": false,
"typeVersion": 1.2,
"alwaysOutputData": false
},
{
"id": "bbdaca8b-ced8-4531-99e0-88af94944352",
"name": "\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u0441\u0442\u0430\u0432 \u0432 \u041f\u0440\u043e\u0444\u0438\u0442\u0435",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueErrorOutput",
"position": [
1056,
-704
],
"parameters": {
"url": "https://my.broker.ru/web/api/v2/newsfeed/posts",
"method": "POST",
"options": {
"redirect": {
"redirect": {}
}
},
"sendBody": true,
"contentType": "multipart-form-data",
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "body",
"value": "={{ $('\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u0441\u0442').item.json.post.toJsonString() }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "authorization",
"value": "=Bearer {{ $json.access_token }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "0b8c343a-567d-45b3-8883-9abe03a34b77",
"name": "\u0420\u0430\u0437\u0432\u0438\u043b\u043a\u0430",
"type": "n8n-nodes-base.switch",
"position": [
528,
-688
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "publish",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "6705dbe2-66e4-4768-9400-e1de6d63b9d5",
"operator": {
"type": "string",
"operation": "startsWith"
},
"leftValue": "={{ $('Get Action Type').item.json.action }}",
"rightValue": "publish"
}
]
},
"renameOutput": true
},
{
"outputKey": "retry",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1d8c2bca-9762-4ee0-ad6b-a3f564e0103d",
"operator": {
"type": "string",
"operation": "startsWith"
},
"leftValue": "={{ $('Get Action Type').item.json.action }}",
"rightValue": "retry"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "40f72a3f-9d40-4319-857a-3372b41732fc",
"name": "\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u0441\u0442",
"type": "n8n-nodes-base.code",
"position": [
704,
-704
],
"parameters": {
"jsCode": "const ticker = $input.first().json.ticker\nconst classCode = $input.first().json.classCode\nconst title = $input.first().json.title\nconst text = $input.first().json.summary\n\nconst post = {\n title: title,\n content: `${text}\\n#\u0422\u0435\u0445\u0430\u043d\u0430\u043b\u0438\u0437 {$${ticker}}`,\n filesInfo: [],\n instruments: [{ securityCode: ticker, classCode: classCode }],\n profiles: [],\n tags: ['\u0422\u0435\u0445\u0430\u043d\u0430\u043b\u0438\u0437'],\n strategies: []\n};\n\nreturn [{ json: { post } }];\n"
},
"typeVersion": 2
},
{
"id": "3a1e1f0f-2b19-4f3e-8ef2-7ff5c1208253",
"name": "Send a text message",
"type": "n8n-nodes-base.telegram",
"position": [
1632,
-336
],
"parameters": {
"text": "=\u041e\u0448\u0438\u0431\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u043e {{ $json.ticker }} - {{ $json.error }}",
"chatId": "{ admin_chat_id }",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c",
"additionalFields": {
"callback_data": "=retry::{{ $('ID Generation').item.json.data }}"
}
}
]
}
}
]
},
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "a332ec95-1e1a-44e1-9e2d-1c3ad24dcde5",
"name": "\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0430",
"type": "n8n-nodes-base.postgres",
"position": [
1248,
-432
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "analytics_history",
"cachedResultName": "analytics_history"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public",
"cachedResultName": "public"
},
"columns": {
"value": {
"id": "={{ $json.data }}",
"title": "={{ $('AI Agent').item.json.output.title }}",
"ticker": "={{ $('\u0420\u0430\u0441\u0441\u0447\u0435\u0442 TA').item.json.context.ticker }}",
"summary": "={{ $('AI Agent').item.json.output.summary }}",
"classCode": "={{ $('\u0420\u0430\u0441\u0441\u0447\u0435\u0442 TA').item.json.context.classCode }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"required": true,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "created_at",
"type": "dateTime",
"display": true,
"required": false,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "summary",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "summary",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "ticker",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ticker",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "classCode",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "classCode",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "title",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "title",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.6
},
{
"id": "cedff92e-feb3-403c-be04-f7fd74ad7fcb",
"name": "\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u0443\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f ticker)",
"type": "n8n-nodes-base.code",
"position": [
0,
-432
],
"parameters": {
"jsCode": "const data = $input.first()?.json;\n\nconst defaultTickers = [ \n { ticker: \"GAZP\", classCode: \"TQBR\" }, \n { ticker: \"SBER\", classCode: \"TQBR\" },\n { ticker: \"LKOH\", classCode: \"TQBR\" }\n];\n\n// \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 ticker \u0438 classCode - \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438\u0445, \u0438\u043d\u0430\u0447\u0435 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435\nconst result = (data?.ticker && data?.classCode) \n ? [{ ticker: data.ticker, classCode: data.classCode }]\n : defaultTickers;\n\nreturn result.map(item => ({ json: item }));"
},
"typeVersion": 2
},
{
"id": "76608d62-aef1-4fa2-b1cd-3bbd03b6b1b9",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-992,
-784
],
"parameters": {
"color": 5,
"width": 700,
"height": 924,
"content": "# \ud83d\udcc8 AI Stock Analytics & BCS \"Profit\" Social Network Publishing Workflow \n\nThis workflow automatically generates stock market insights for selected tickers (e.g. GAZP, SBER, LKOH) using historical data, technical indicators, and an AI model. The results are then sent to Telegram for quick moderation and publishing. \n\n## \ud83d\udd11 What this workflow does\n- **Runs twice a day** on a schedule with a predefined list of tickers. \n- **Fetches historical market data** from a broker API. \n- **Calculates key technical indicators** (RSI, EMA/SMA, MACD, Bollinger Bands, ADX). \n- **Generates an investment post** (title + summary) using an LLM. \n- **Stores results** in a PostgreSQL database. \n- **Sends a draft post to Telegram** with inline buttons *\u201cPublish\u201d* and *\u201cRetry\u201d*. \n- **Handles Telegram actions**: publishes the post to the final channel or re-runs the generation process. \n\n## \ud83d\udccc Key features\n- Multi-ticker support in a single run. \n- Automatic error handling (e.g. missing data or invalid AI JSON output). \n- Human-in-the-loop moderation through Telegram before publishing. \n- PostgreSQL integration for history and analytics storage. \n- Flexible structure: easy to extend with new tickers, indicators, or publishing channels. \n\n## \ud83d\udee0\ufe0f Nodes used\n- **Trigger:** Schedule (twice daily) + Telegram Trigger (button callbacks). \n- **Data:** HTTP Request (broker API), Function (technical analysis calculations). \n- **AI:** OpenAI / OpenRouter with structured JSON output. \n- **Storage:** PostgreSQL (analytics history). \n- **Messaging:** Telegram (drafts and publishing). \n\n## \ud83d\ude80 Who is this for\n- Fintech startups looking to automate market content. \n- Investment bloggers posting daily stock analysis. \n- Analysts experimenting with trading strategies on real market data. \n"
},
"typeVersion": 1
},
{
"id": "a42b6f27-bdd6-412a-96b5-d8d3b2ca6271",
"name": "Query callback",
"type": "n8n-nodes-base.telegram",
"position": [
-16,
-832
],
"parameters": {
"queryId": "={{ $json.callback_query.id }}",
"resource": "callback",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "55d6ca44-7fdd-4132-a10a-85d2b67eb554",
"connections": {
"AI Agent": {
"main": [
[
{
"node": "ID Generation",
"type": "main",
"index": 0
}
],
[
{
"node": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438",
"type": "main",
"index": 0
}
]
]
},
"ID Generation": {
"main": [
[
{
"node": "\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0430",
"type": "main",
"index": 0
}
]
]
},
"Get Post By Id": {
"main": [
[
{
"node": "\u0420\u0430\u0437\u0432\u0438\u043b\u043a\u0430",
"type": "main",
"index": 0
}
]
]
},
"Get Action Type": {
"main": [
[
{
"node": "Exist type and id",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u0443\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f ticker)",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "Get Action Type",
"type": "main",
"index": 0
},
{
"node": "Query callback",
"type": "main",
"index": 0
}
]
]
},
"\u0420\u0430\u0437\u0432\u0438\u043b\u043a\u0430": {
"main": [
[
{
"node": "\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u0441\u0442",
"type": "main",
"index": 0
}
],
[
{
"node": "\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u0443\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f ticker)",
"type": "main",
"index": 0
}
]
]
},
"Exist type and id": {
"main": [
[
{
"node": "Get Post By Id",
"type": "main",
"index": 0
}
],
[
{
"node": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438",
"type": "main",
"index": 0
}
]
]
},
"\u0420\u0430\u0441\u0441\u0447\u0435\u0442 TA": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Execute Auth Login": {
"main": [
[
{
"node": "\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u0441\u0442\u0430\u0432 \u0432 \u041f\u0440\u043e\u0444\u0438\u0442\u0435",
"type": "main",
"index": 0
}
]
]
},
"OpenRouter Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
},
{
"node": "Structured Output Parser",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Execute Auth Trade API": {
"main": [
[
{
"node": "\u0418\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Agent",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u0441\u0442": {
"main": [
[
{
"node": "Execute Auth Login",
"type": "main",
"index": 0
}
]
]
},
"\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0430": {
"main": [
[
{
"node": "\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0441\u0442\u0430 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e",
"type": "main",
"index": 0
}
]
]
},
"\u0418\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435": {
"main": [
[
{
"node": "\u0420\u0430\u0441\u0441\u0447\u0435\u0442 TA",
"type": "main",
"index": 0
}
]
]
},
"\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e\u0441\u0442\u0430 \u043d\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e": {
"main": [
[],
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
},
"\u041f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u043e\u0441\u0442\u0430\u0432 \u0432 \u041f\u0440\u043e\u0444\u0438\u0442\u0435": {
"main": [
[
{
"node": "\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e",
"type": "main",
"index": 0
}
],
[
{
"node": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438",
"type": "main",
"index": 0
}
]
]
},
"\u0414\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u0442\u0443\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f ticker)": {
"main": [
[
{
"node": "Execute Auth Trade API",
"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.
openRouterApipostgrestelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically generates stock market insights for selected tickers (e.g. GAZP, SBER, LKOH) using historical data, technical indicators, and an AI model. The results are then sent to Telegram for quick moderation and publishing. Runs twice a day on a schedule with a…
Source: https://n8n.io/workflows/8094/ — 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.
System Architecture Two integrated N8N workflows providing automated US stock portfolio management through Telegram:
This cutting-edge n8n workflow is a comprehensive automation solution designed to streamline various Instagram operations. It combines an intelligent AI chatbot for direct message management, automate
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing
RAG CHATBOT Main. Uses telegram, telegramTrigger, lmChatOpenAi, n8n-nodes-mcp. Event-driven trigger; 87 nodes.