{
  "meta": {
    "instanceId": "6c3d8936583f8a98fa8ebe06f510117c0e8fff2df771e73deba4126a853eb55e"
  },
  "nodes": [
    {
      "id": "a9bbe9d0-51aa-40f8-8931-f405c695c732",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        1140,
        140
      ],
      "parameters": {
        "sessionKey": "=335458847",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "2d6315d6-959d-4e16-97ed-30839d826ce2",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1080,
        -100
      ],
      "parameters": {
        "text": "=Ticker = {{ $json["Ticker symbol:"] }}",
        "options": {
          "systemMessage": "=# OverviewnYou are an AI agent specialized in stock analysis. You provide technical analysis and sentiment for stock investments by combining chart data and news sentiment.nn# Instructionsn1. When a user requests an analysis of a stock with its symbol:n  - Send the stock symbol to both tools **technical_analysis** and **trends_analysis**n  - Analyze the combined data and prepare a JSON report with your insightsn  - Provide a clear recommendation (positive, neutral, or negative)n2. Your output must be in the format of a structured JSON object that will be used to fill an HTML template.n3. Translate the article titles in topArticles to Hebrewn4. Translate the sentimentHebrew results to only one of these values:n"u05d7u05d9u05d5u05d1u05d9-u05d7u05d6u05e7/u05d7u05d9u05d5u05d1u05d9-u05d7u05dcu05e9/u05e0u05d9u05d9u05d8u05e8u05dcu05d9/u05e9u05dcu05d9u05dcu05d9-u05d7u05dcu05e9/u05e9u05dcu05d9u05dcu05d9-u05d7u05d6u05e7". Somewhat=u05d7u05dcu05e9.n5. Write the Date value in each article: "topArticles" only in this format: "DD/MM/YYYY".n6. Update the technicalAnalysis value as a detailed technical analysis of three paragraphs, which explains even to those who don't understand economics what you did and how you reached your conclusions. Touch on all the indicators examined (Volume, EMA, RSI, Fibonacci retracement, MACD, Bollinger bands, Resistance and support levels)n7. Ensure that the text in the technicalAnalysis value is written in proper Hebrew, like a professional analyst. Use the think tooln8. In the Recommendation value - recommend to buy or sell only if you think with high probability that there will be a rise or fall. Use the think tool to verify your Recommendation based on recommendationText. Advise something only if you really believe it. Your default is the "u05deu05deu05dcu05d9u05e5 u05dcu05d7u05dbu05d5u05ea" value.nn## Toolsn- **technical_analysis**: Generates technical analysis based on stock chartsn- **trends_analysis**: Analyzes news sentiment for the requested stocknn## Response FormatnYou must respond with a JSON object containing exactly the following keys to fill the HTML template:nn```jsonn{n "stockSymbol": "u05e1u05d9u05deu05d5u05dc",n "analysisDate": "DD/MM/YYYY",n "recommendationClass": "positive/neutral/negative",n "recommendationTitle": "u05dbu05d5u05eau05e8u05ea u05d4u05deu05dcu05e6u05d4 u05d1u05e2u05d1u05e8u05d9u05ea",n "recommendationText": "u05d4u05e1u05d1u05e8 u05deu05e4u05d5u05e8u05d8 u05e9u05dc u05d4u05d4u05deu05dcu05e6u05d4 u05d1u05e2u05d1u05e8u05d9u05ea",n "bullishCount": 0,n "neutralCount": 0, n "bearishCount": 0,n "bullishHeight": 0,n "neutralHeight": 0,n "bearishHeight": 0,n "overallSentiment": "u05d7u05d9u05d5u05d1u05d9/u05e0u05d9u05d9u05d8u05e8u05dcu05d9/u05e9u05dcu05d9u05dcu05d9",n "Recommendation": "u05deu05deu05dcu05d9u05e5 u05dcu05e7u05e0u05d5u05ea/ u05deu05deu05dcu05d9u05e5 u05dcu05d7u05dbu05d5u05ea/ u05deu05deu05dcu05d9u05e5 u05dcu05deu05dbu05d5u05e8",n "sentimentScore": 0.00,n "chartImageUrl": "URL_PLACEHOLDER",n "technicalAnalysis": "u05e0u05d9u05eau05d5u05d7 u05d8u05dbu05e0u05d9 u05deu05e4u05d5u05e8u05d8 u05d1u05e2u05d1u05e8u05d9u05ea u05e2u05dd u05eau05d2u05d9 <p>",n "topArticles": [n   {n     "title": "u05dbu05d5u05eau05e8u05ea u05d4u05deu05d0u05deu05e8 u05d1u05e2u05d1u05e8u05d9u05ea",n     "url": "u05dbu05eau05d5u05d1u05ea URL u05e9u05dc u05d4u05deu05d0u05deu05e8",n     "source": "u05e9u05dd u05d4u05deu05e7u05d5u05e8 u05d1u05d0u05e0u05d2u05dcu05d9u05ea",n     "date": "DD/MM/YYYY",n     "sentimentClass": "bullish/neutral/bearish",n     "sentimentHebrew": "u05d7u05d9u05d5u05d1u05d9-u05d7u05d6u05e7/u05d7u05d9u05d5u05d1u05d9-u05d7u05dcu05e9/u05e0u05d9u05d9u05d8u05e8u05dcu05d9/u05e9u05dcu05d9u05dcu05d9-u05d7u05dcu05e9/u05e9u05dcu05d9u05dcu05d9-u05d7u05d6u05e7"n   }n ],n "hotTopics": [n   {n     "topic": "u05e9u05dd u05d4u05e0u05d5u05e9u05d0 u05d1u05e2u05d1u05e8u05d9u05ea",n     "article_count": 0,n     "average_relevance": "0.00"n   }n ]n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "14112026-19eb-493f-971b-28455a8d4412",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        680,
        -220
      ],
      "parameters": {
        "color": 4,
        "width": 1820,
        "height": 580,
        "content": "# AI AgentnAI agent powered by GPT-4o that analyses stocks by combining technical analysis and news sentiment, generating detailed reports in Hebrew with data-driven investment recommendations"
      },
      "typeVersion": 1
    },
    {
      "id": "8b2e573e-7acc-4b0b-a708-4ce33873a893",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        680,
        380
      ],
      "parameters": {
        "width": 2820,
        "height": 920,
        "content": "# Technical Analysis ToolnA tool that performs in-depth technical analysis of stock charts by combining visual pattern recognition with quantitative indicators. It fetches data from Chart-img API for generating visual charts, Twelve Data API for historical prices and technical indicators (Bollinger Bands, MACD), and uses OpenAI's GPT-4o for visual chart pattern recognition.nThe system synthesizes this multi-source data into a comprehensive technical assessment with actionable trading insights based on support/resistance levels, Fibonacci retracements, and candlestick patterns."
      },
      "typeVersion": 1
    },
    {
      "id": "b0d49fa6-5c57-4ab5-a752-93d7d278b8fa",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2520,
        -220
      ],
      "parameters": {
        "width": 980,
        "height": 580,
        "content": "# Trends Analysis ToolnA tool that analyses news sentiment for requested stocks by fetching recent financial news articles, calculating sentiment metrics, identifying influential stories, and extracting trending topics. It processes data from Alpha Vantage's news API, determines overall market sentiment, and delivers structured analysis on stock sentiment, relevance, and market outlook."
      },
      "typeVersion": 1
    },
    {
      "id": "13a242cf-0a01-4aea-a58e-9b734aed912c",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1900,
        140
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{n  "stockSymbol": "u05e1u05d9u05deu05d5u05dc",n  "analysisDate": "DD/MM/YYYY",n  "recommendationClass": "positive/neutral/negative",n  "recommendationTitle": "u05dbu05d5u05eau05e8u05ea u05d4u05deu05dcu05e6u05d4 u05d1u05e2u05d1u05e8u05d9u05ea",n  "recommendationText": "u05d4u05e1u05d1u05e8 u05deu05e4u05d5u05e8u05d8 u05e9u05dc u05d4u05d4u05deu05dcu05e6u05d4 u05d1u05e2u05d1u05e8u05d9u05ea",n  "bullishCount": 0,n  "neutralCount": 0, n  "bearishCount": 0,n  "bullishHeight": 0,n  "neutralHeight": 0,n  "bearishHeight": 0,n  "overallSentiment": "u05d7u05d9u05d5u05d1u05d9/u05e0u05d9u05d9u05d8u05e8u05dcu05d9/u05e9u05dcu05d9u05dcu05d9",n  "Recommendation": "u05deu05deu05dcu05d9u05e5 u05dcu05e7u05e0u05d5u05ea/ u05deu05deu05dcu05d9u05e5 u05dcu05d7u05dbu05d5u05ea/ u05deu05deu05dcu05d9u05e5 u05dcu05deu05dbu05d5u05e8",n  "sentimentScore": 0.00,n  "chartImageUrl": "URL_PLACEHOLDER",n  "technicalAnalysis": "u05e0u05d9u05eau05d5u05d7 u05d8u05dbu05e0u05d9 u05deu05e4u05d5u05e8u05d8 u05d1u05e2u05d1u05e8u05d9u05ea u05e2u05dd u05eau05d2u05d9 <p>",n  "topArticles": [n    {n      "title": "u05dbu05d5u05eau05e8u05ea u05d4u05deu05d0u05deu05e8",n      "url": "u05dbu05eau05d5u05d1u05ea URL u05e9u05dc u05d4u05deu05d0u05deu05e8",n      "source": "u05e9u05dd u05d4u05deu05e7u05d5u05e8",n      "date": "DD/MM/YYYY",n      "sentimentClass": "bullish/neutral/bearish",n      "sentimentHebrew": "u05d7u05d9u05d5u05d1u05d9-u05d7u05d6u05e7/u05d7u05d9u05d5u05d1u05d9-u05d7u05dcu05e9/u05e0u05d9u05d9u05d8u05e8u05dcu05d9/u05e9u05dcu05d9u05dcu05d9-u05d7u05dcu05e9/u05e9u05dcu05d9u05dcu05d9-u05d7u05d6u05e7"n    }n  ],n  "hotTopics": [n    {n      "topic": "u05e9u05dd u05d4u05e0u05d5u05e9u05d0 u05d1u05e2u05d1u05e8u05d9u05ea",n      "article_count": 0,n      "average_relevance": "0.00"n    }n  ]n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "bb5dd63a-a3e6-408e-a5c9-13e9f72f2b26",
      "name": "GPT 4o",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        960,
        140
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "gpt-4o"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "2m1HH5crgPAhTJlv",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "94d820d2-eb20-4184-8e21-1ed5936c9166",
      "name": "Generate HTML",
      "type": "n8n-nodes-base.html",
      "position": [
        1860,
        -100
      ],
      "parameters": {
        "html": "nnn    n    n    <title>u05e0u05d9u05eau05d5u05d7 u05deu05e0u05d9u05d9u05ea {{ $('AI Agent').item.json.output.stockSymbol }}</title>nnn    <!-- u05e2u05d5u05d8u05e3 u05e8u05d0u05e9u05d9 -->n    <div style="max-width: 650px;margin: 0 auto;background-color: #ffffff;border-radius: 16px;overflow: hidden;margin-top: 30px;margin-bottom: 30px;text-align: right;direction: rtl">n        n        <!-- u05dbu05d5u05eau05e8u05ea u05e2u05dcu05d9u05d5u05e0u05d4 -->n        <div style="background: linear-gradient(135deg, #0057ff 0%, #00b2ff 100%);padding: 30px 40px;text-align: center;position: relative;overflow: hidden;margin-bottom: 20px">n            <div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;opacity: 0.2"></div>n            <h1 style="color: #ffffff;font-weight: 700;font-size: 28px;margin: 0 0 5px 0;letter-spacing: -0.5px;position: relative">u05e0u05d9u05eau05d5u05d7 u05deu05e0u05d9u05d9u05ea {{ $('AI Agent').item.json.output.stockSymbol }}</h1>n            <div style="font-size: 15px;position: relative">u05eau05d0u05e8u05d9u05da: {{ $('AI Agent').item.json.output.analysisDate }}</div>n        </div>n        n        <!-- u05eau05d5u05dbu05df u05d4u05deu05d9u05d9u05dc -->n        <div style="padding: 40px;text-align: right;direction: rtl">n            n            <!-- u05eau05d9u05d1u05ea u05d4u05deu05dcu05e6u05d4 -->n            <div style="background-color: #f8fafc;border-radius: 12px;padding: 25px;margin-bottom: 40px;position: relative;overflow: hidden;text-align: right">n                <div style="position: absolute;right: 0;top: 0;bottom: 0;width: 6px;background-color: #f7b955"></div>n                <div style="position: absolute;right: 0;top: 0;width: 100%;height: 100%;background: linear-gradient(90deg, rgba(247, 185, 85, 0.07) 0%, rgba(247, 185, 85, 0) 50%)"></div>n                <div style="text-align: center;position: relative">n                    <div style="width: 40px;height: 40px;border-radius: 50%;margin-bottom: 10px;text-align: center">n                        <span style="font-size: 20px;line-height: 40px">u2696ufe0f</span>n                    </div>n                    <h2 style="margin: 0 0 10px 0;color: #f7b955;font-size: 22px;font-weight: 700;text-align: center">{{ $('AI Agent').item.json.output.recommendationTitle }}</h2>n                    <p style="margin: 0;font-size: 16px;line-height: 1.6;color: #4a5568;text-align: right">{{ $json.message.content.recommendationText }}</p>n                    <div style="margin-top: 25px">n                        <a style="background-color: #29cc7a;color: white;font-weight: 600;font-size: 16px;padding: 12px 30px;border-radius: 8px;text-decoration: none">{{ $('AI Agent').item.json.output.Recommendation }}</a>n                    </div>n                </div>n            </div>nn            <!-- u05e0u05d9u05eau05d5u05d7 u05d8u05dbu05e0u05d9 -->n            <div style="margin-bottom: 40px;text-align: right">n                <h2 style="font-size: 20px;color: #1a202c;margin: 0 0 20px 0;padding-bottom: 12px;border-bottom: 1px solid #edf2f7;font-weight: 700;text-align: right">u05e0u05d9u05eau05d5u05d7 u05d8u05dbu05e0u05d9</h2>n                n                <div style="background: #ffffff;border-radius: 12px;overflow: hidden;margin-bottom: 25px">n                    <img src="{{ $('AI Agent').item.json.output.chartImageUrl }}" alt="u05d2u05e8u05e3 u05d8u05dbu05e0u05d9 {{ $('AI Agent').item.json.output.stockSymbol }}" style="width: 100%;max-height: 450px;object-fit: contain">n                </div>n                n                <div style="background-color: #f8fafc;border-radius: 12px;padding: 25px;font-size: 15px;line-height: 1.6;color: #4a5568;text-align: right">n                    {{ $json.message.content.technicalAnalysis }}n                </div>n            </div>n                      n            <!-- u05e0u05d9u05eau05d5u05d7 u05e1u05e0u05d8u05d9u05deu05e0u05d8 -->n            <div style="margin-bottom: 40px;text-align: right">n                <h2 style="font-size: 20px;color: #1a202c;margin: 0 0 20px 0;padding-bottom: 12px;border-bottom: 1px solid #edf2f7;font-weight: 700;text-align: right">u05e0u05d9u05eau05d5u05d7 u05e1u05e0u05d8u05d9u05deu05e0u05d8 u05e9u05d5u05e7</h2>n                n                <!-- u05d2u05e8u05e3 u05e1u05e0u05d8u05d9u05deu05e0u05d8 - u05e2u05dd u05d8u05d1u05dcu05d4 u05d1u05deu05e7u05d5u05dd flex -->n                <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;margin: 45px 0 30px 0">n                    <tr valign="bottom" align="center">n                        <td width="33%" style="text-align: center;padding: 0 10px">n                            <div style="font-weight: 600;margin-bottom: 10px;color: #29cc7a">{{ $('AI Agent').item.json.output.bullishCount }}</div>n                            <div style="background-color: #29cc7a;border-radius: 8px 8px 0 0;width: 100%;margin: 0 auto;opacity: 0.85"></div>n                            <div style="font-size: 14px;color: #4a5568;margin-top: 10px">u05d7u05d9u05d5u05d1u05d9</div>n                        </td>n                        <td width="33%" style="text-align: center;padding: 0 10px">n                            <div style="font-weight: 600;margin-bottom: 10px;color: #f7b955">{{ $('AI Agent').item.json.output.neutralCount }}</div>n                            <div style="background-color: #f7b955;border-radius: 8px 8px 0 0;width: 100%;margin: 0 auto;opacity: 0.85"></div>n                            <div style="font-size: 14px;color: #4a5568;margin-top: 10px">u05e0u05d9u05d9u05d8u05e8u05dcu05d9</div>n                        </td>n                        <td width="33%" style="text-align: center;padding: 0 10px">n                            <div style="font-weight: 600;margin-bottom: 10px;color: #f55e5e">{{ $('AI Agent').item.json.output.bearishCount }}</div>n                            <div style="background-color: #f55e5e;border-radius: 8px 8px 0 0;width: 100%;margin: 0 auto;opacity: 0.85"></div>n                            <div style="font-size: 14px;color: #4a5568;margin-top: 10px">u05e9u05dcu05d9u05dcu05d9</div>n                        </td>n                    </tr>n                </table>n                n                <div style="background-color: #f8fafc;border-radius: 10px;padding: 15px;text-align: center;font-size: 15px">n                    u05d4u05e1u05e0u05d8u05d9u05deu05e0u05d8 u05d4u05dbu05dcu05dcu05d9 u05dcu05deu05e0u05d9u05d9u05ea <strong>{{ $('AI Agent').item.json.output.stockSymbol }}</strong> u05d4u05d5u05d0 n                    <span style="font-weight: 600;color: #f7b955">{{ $('AI Agent').item.json.output.overallSentiment }}</span> n                    u05e2u05dd u05e6u05d9u05d5u05df u05e9u05dc <strong>{{ $('AI Agent').item.json.output.sentimentScore }}</strong>n                </div>n            </div>n            n            <!-- u05deu05d0u05deu05e8u05d9u05dd u05deu05e9u05e4u05d9u05e2u05d9u05dd -->n            <div style="margin-bottom: 40px;text-align: right">n                <h2 style="font-size: 20px;color: #1a202c;margin: 0 0 20px 0;padding-bottom: 12px;border-bottom: 1px solid #edf2f7;font-weight: 700;text-align: right">u05deu05d0u05deu05e8u05d9u05dd u05deu05e9u05e4u05d9u05e2u05d9u05dd</h2>n                n                <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse">n                    <!-- u05deu05d0u05deu05e8 1 -->n                    <tr>n                        <td style="padding-bottom: 16px">n                            <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;background-color: #f8fafc;border-radius: 12px;overflow: hidden">n                                <tr>n                                    <td width="4" style="background-color: #f7b955"></td>n                                    <td style="padding: 18px 22px">n                                        <h3 style="margin: 0 0 8px 0;font-size: 16px;font-weight: 600;line-height: 1.4;text-align: right">n                                            <a href="{{ $('AI Agent').item.json.output.topArticles[0].url }}" target="_blank" style="color: #2b6cb0;text-decoration: none">{{ $('AI Agent').item.json.output.topArticles[0].title }}</a>n                                        </h3>n                                        <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;margin-top: 10px">n                                            <tr>n                                                <td style="font-size: 13px;color: #718096;text-align: right">{{ $('AI Agent').item.json.output.topArticles[0].source }} | {{ $('AI Agent').item.json.output.topArticles[0].date }}</td>n                                                <td style="text-align: left">n                                                    <div style="padding: 3px 10px;border-radius: 30px;font-weight: 500;font-size: 12px;color: #f7b955">n                                                        {{ $('AI Agent').item.json.output.topArticles[0].sentimentHebrew }}n                                                    </div>n                                                </td>n                                            </tr>n                                        </table>n                                    </td>n                                </tr>n                            </table>n                        </td>n                    </tr>n                    n                    <!-- u05deu05d0u05deu05e8 2 -->n                    <tr>n                        <td style="padding-bottom: 16px">n                            <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;background-color: #f8fafc;border-radius: 12px;overflow: hidden">n                                <tr>n                                    <td width="4" style="background-color: #f7b955"></td>n                                    <td style="padding: 18px 22px">n                                        <h3 style="margin: 0 0 8px 0;font-size: 16px;font-weight: 600;line-height: 1.4;text-align: right">n                                            <a href="{{ $('AI Agent').item.json.output.topArticles[1].url }}" target="_blank" style="color: #2b6cb0;text-decoration: none">{{ $('AI Agent').item.json.output.topArticles[1].title }}</a>n                                        </h3>n                                        <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;margin-top: 10px">n                                            <tr>n                                                <td style="font-size: 13px;color: #718096;text-align: right">{{ $('AI Agent').item.json.output.topArticles[1].source }} | {{ $('AI Agent').item.json.output.topArticles[1].date }}</td>n                                                <td style="text-align: left">n                                                    <div style="padding: 3px 10px;border-radius: 30px;font-weight: 500;font-size: 12px;color: #f7b955">n                                                        {{ $('AI Agent').item.json.output.topArticles[1].sentimentHebrew }}n                                                    </div>n                                                </td>n                                            </tr>n                                        </table>n                                    </td>n                                </tr>n                            </table>n                        </td>n                    </tr>n                    n                    <!-- u05deu05d0u05deu05e8 3 -->n                    <tr>n                        <td style="padding-bottom: 16px">n                            <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;background-color: #f8fafc;border-radius: 12px;overflow: hidden">n                                <tr>n                                    <td width="4" style="background-color: #f7b955"></td>n                                    <td style="padding: 18px 22px">n                                        <h3 style="margin: 0 0 8px 0;font-size: 16px;font-weight: 600;line-height: 1.4;text-align: right">n                                            <a href="{{ $('AI Agent').item.json.output.topArticles[2].url }}" target="_blank" style="color: #2b6cb0;text-decoration: none">{{ $('AI Agent').item.json.output.topArticles[2].title }}</a>n                                        </h3>n                                        <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;margin-top: 10px">n                                            <tr>n                                                <td style="font-size: 13px;color: #718096;text-align: right">{{ $('AI Agent').item.json.output.topArticles[2].source }} | {{ $('AI Agent').item.json.output.topArticles[2].date }}</td>n                                                <td style="text-align: left">n                                                    <div style="padding: 3px 10px;border-radius: 30px;font-weight: 500;font-size: 12px;color: #f7b955">n                                                        {{ $('AI Agent').item.json.output.topArticles[2].sentimentHebrew }}n                                                    </div>n                                                </td>n                                            </tr>n                                        </table>n                                    </td>n                                </tr>n                            </table>n                        </td>n                    </tr>n                    n                    <!-- u05deu05d0u05deu05e8 4 -->n                    <tr>n                        <td style="padding-bottom: 16px">n                            <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;background-color: #f8fafc;border-radius: 12px;overflow: hidden">n                                <tr>n                                    <td width="4" style="background-color: #f7b955"></td>n                                    <td style="padding: 18px 22px">n                                        <h3 style="margin: 0 0 8px 0;font-size: 16px;font-weight: 600;line-height: 1.4;text-align: right">n                                            <a href="{{ $('AI Agent').item.json.output.topArticles[3].url }}" target="_blank" style="color: #2b6cb0;text-decoration: none">{{ $('AI Agent').item.json.output.topArticles[3].title }}</a>n                                        </h3>n                                        <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;margin-top: 10px">n                                            <tr>n                                                <td style="font-size: 13px;color: #718096;text-align: right">{{ $('AI Agent').item.json.output.topArticles[3].source }} | {{ $('AI Agent').item.json.output.topArticles[3].date }}</td>n                                                <td style="text-align: left">n                                                    <div style="padding: 3px 10px;border-radius: 30px;font-weight: 500;font-size: 12px;color: #f7b955">n                                                        {{ $('AI Agent').item.json.output.topArticles[3].sentimentHebrew }}n                                                    </div>n                                                </td>n                                            </tr>n                                        </table>n                                    </td>n                                </tr>n                            </table>n                        </td>n                    </tr>n                    n                    <!-- u05deu05d0u05deu05e8 5 -->n                    <tr>n                        <td style="padding-bottom: 16px">n                            <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;background-color: #f8fafc;border-radius: 12px;overflow: hidden">n                                <tr>n                                    <td width="4" style="background-color: #f7b955"></td>n                                    <td style="padding: 18px 22px">n                                        <h3 style="margin: 0 0 8px 0;font-size: 16px;font-weight: 600;line-height: 1.4;text-align: right">n                                            <a href="{{ $('AI Agent').item.json.output.topArticles[4].url }}" target="_blank" style="color: #2b6cb0;text-decoration: none">{{ $('AI Agent').item.json.output.topArticles[4].title }}</a>n                                        </h3>n                                        <table cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;margin-top: 10px">n                                            <tr>n                                                <td style="font-size: 13px;color: #718096;text-align: right">{{ $('AI Agent').item.json.output.topArticles[4].source }} | {{ $('AI Agent').item.json.output.topArticles[4].date }}</td>n                                                <td style="text-align: left">n                                                    <div style="padding: 3px 10px;border-radius: 30px;font-weight: 500;font-size: 12px;color: #f7b955">n                                                        {{ $('AI Agent').item.json.output.topArticles[4].sentimentHebrew }}n                                                    </div>n                                                </td>n                                            </tr>n                                        </table>n                                    </td>n                                </tr>n                            </table>n                        </td>n                    </tr>n                </table>n            </div>n              n    <!-- u05e0u05d5u05e9u05d0u05d9u05dd u05d7u05deu05d9u05dd - u05d2u05e8u05e1u05d4 u05deu05e9u05d5u05e4u05e8u05ea u05dcu05deu05d5u05d1u05d9u05d9u05dc -->n    <div style="margin-bottom: 30px;text-align: right">n        <h2 style="font-size: 20px;color: #1a202c;margin: 0 0 20px 0;padding-bottom: 12px;border-bottom: 1px solid #edf2f7;font-weight: 700;text-align: right">u05e0u05d5u05e9u05d0u05d9u05dd u05d7u05deu05d9u05dd</h2>n        n        <div style="background-color: #f8fafc;border-radius: 12px;padding: 20px 25px;text-align: right">n            <p style="margin: 0 0 15px 0;font-size: 15px;color: #4a5568;text-align: right">u05d4u05e0u05d5u05e9u05d0u05d9u05dd u05d4u05deu05e8u05dbu05d6u05d9u05d9u05dd u05e9u05deu05d5u05e4u05d9u05e2u05d9u05dd u05d1u05d7u05d3u05e9u05d5u05ea u05e2u05dc {{ $('AI Agent').item.json.output.stockSymbol }}:</p>n            n            <!-- u05e0u05d5u05e9u05d0 1 -->n            <div style="margin-bottom: 15px;padding-bottom: 15px;border-bottom: 1px solid #edf2f7">n                <div style="width: 100%;margin-bottom: 8px">n                    <div style="vertical-align: middle;text-align: right;font-weight: 600;font-size: 15px">n                        {{ $('AI Agent').item.json.output.hotTopics[0].topic }}n                    </div>n                    <div style="vertical-align: middle;text-align: left">n                        <div style="background-color: #edf2f7;border-radius: 30px;padding: 4px 12px;font-size: 13px;color: #4a5568;text-align: center">n                            <strong>{{ $('AI Agent').item.json.output.hotTopics[0].article_count }}</strong> u05deu05d0u05deu05e8u05d9u05ddn                        </div>n                    </div>n                </div>n                <div style="background-color: #e2e8f0;height: 4px;width: 100%;border-radius: 2px;overflow: hidden">n                    <div style="background-color: #4299e1;height: 100%;width: calc({{ $('AI Agent').item.json.output.hotTopics[0].average_relevance }} * 100%)"></div>n                </div>n                <div style="text-align: left;font-size: 12px;color: #718096;margin-top: 4px">u05e8u05dcu05d5u05d5u05e0u05d8u05d9u05d5u05ea: {{ $('AI Agent').item.json.output.hotTopics[0].average_relevance }}</div>n            </div>n            n            <!-- u05e0u05d5u05e9u05d0 2 -->n            <div style="margin-bottom: 15px;padding-bottom: 15px;border-bottom: 1px solid #edf2f7">n                <div style="width: 100%;margin-bottom: 8px">n                    <div style="vertical-align: middle;text-align: right;font-weight: 600;font-size: 15px">n                        {{ $('AI Agent').item.json.output.hotTopics[1].topic }}n                    </div>n                    <div style="vertical-align: middle;text-align: left">n                        <div style="background-color: #edf2f7;border-radius: 30px;padding: 4px 12px;font-size: 13px;color: #4a5568;text-align: center">n                            <strong>{{ $('AI Agent').item.json.output.hotTopics[1].article_count }}</strong> u05deu05d0u05deu05e8u05d9u05ddn                        </div>n                    </div>n                </div>n                <div style="background-color: #e2e8f0;height: 4px;width: 100%;border-radius: 2px;overflow: hidden">n                    <div style="background-color: #4299e1;height: 100%;width: calc({{ $('AI Agent').item.json.output.hotTopics[1].average_relevance }} * 100%)"></div>n                </div>n                <div style="text-align: left;font-size: 12px;color: #718096;margin-top: 4px">u05e8u05dcu05d5u05d5u05e0u05d8u05d9u05d5u05ea: {{ $('AI Agent').item.json.output.hotTopics[1].average_relevance }}</div>n            </div>n            n            <!-- u05e0u05d5u05e9u05d0 3 -->n            <div style="margin-bottom: 15px;padding-bottom: 15px;border-bottom: 1px solid #edf2f7">n                <div style="width: 100%;margin-bottom: 8px">n                    <div style="vertical-align: middle;text-align: right;font-weight: 600;font-size: 15px">n                        {{ $('AI Agent').item.json.output.hotTopics[2].topic }}n                    </div>n                    <div style="vertical-align: middle;text-align: left">n                        <div style="background-color: #edf2f7;border-radius: 30px;padding: 4px 12px;font-size: 13px;color: #4a5568;text-align: center">n                            <strong>{{ $('AI Agent').item.json.output.hotTopics[2].article_count }}</strong> u05deu05d0u05deu05e8u05d9u05ddn                        </div>n                    </div>n                </div>n                <div style="background-color: #e2e8f0;height: 4px;width: 100%;border-radius: 2px;overflow: hidden">n                    <div style="background-color: #4299e1;height: 100%;width: calc({{ $('AI Agent').item.json.output.hotTopics[2].average_relevance }} * 100%)"></div>n                </div>n                <div style="text-align: left;font-size: 12px;color: #718096;margin-top: 4px">u05e8u05dcu05d5u05d5u05e0u05d8u05d9u05d5u05ea: {{ $('AI Agent').item.json.output.hotTopics[2].average_relevance }}</div>n            </div>n            n            <!-- u05e0u05d5u05e9u05d0 4 -->n            <div style="margin-bottom: 15px;padding-bottom: 15px;border-bottom: 1px solid #edf2f7">n                <div style="width: 100%;margin-bottom: 8px">n                    <div style="vertical-align: middle;text-align: right;font-weight: 600;font-size: 15px">n                        {{ $('AI Agent').item.json.output.hotTopics[3].topic }}n                    </div>n                    <div style="vertical-align: middle;text-align: left">n                        <div style="background-color: #edf2f7;border-radius: 30px;padding: 4px 12px;font-size: 13px;color: #4a5568;text-align: center">n                            <strong>{{ $('AI Agent').item.json.output.hotTopics[3].article_count }}</strong> u05deu05d0u05deu05e8u05d9u05ddn                        </div>n                    </div>n                </div>n                <div style="background-color: #e2e8f0;height: 4px;width: 100%;border-radius: 2px;overflow: hidden">n                    <div style="background-color: #4299e1;height: 100%;width: calc({{ $('AI Agent').item.json.output.hotTopics[3].average_relevance }} * 100%)"></div>n                </div>n                <div style="text-align: left;font-size: 12px;color: #718096;margin-top: 4px">u05e8u05dcu05d5u05d5u05e0u05d8u05d9u05d5u05ea: {{ $('AI Agent').item.json.output.hotTopics[3].average_relevance }}</div>n            </div>n            n            <!-- u05e0u05d5u05e9u05d0 5 -->n            <div style="margin-bottom: 0">n                <div style="width: 100%;margin-bottom: 8px">n                    <div style="vertical-align: middle;text-align: right;font-weight: 600;font-size: 15px">n                        {{ $('AI Agent').item.json.output.hotTopics[4].topic }}n                    </div>n                    <div style="vertical-align: middle;text-align: left">n                        <div style="background-color: #edf2f7;border-radius: 30px;padding: 4px 12px;font-size: 13px;color: #4a5568;text-align: center">n                            <strong>{{ $('AI Agent').item.json.output.hotTopics[4].article_count }}</strong> u05deu05d0u05deu05e8u05d9u05ddn                        </div>n                    </div>n                </div>n                <div style="background-color: #e2e8f0;height: 4px;width: 100%;border-radius: 2px;overflow: hidden">n                    <div style="background-color: #4299e1;height: 100%;width: calc({{ $('AI Agent').item.json.output.hotTopics[4].average_relevance }} * 100%)"></div>n                </div>n                <div style="text-align: left;font-size: 12px;color: #718096;margin-top: 4px">u05e8u05dcu05d5u05d5u05e0u05d8u05d9u05d5u05ea: {{ $('AI Agent').item.json.output.hotTopics[4].average_relevance }}</div>n            </div>n        </div>n    </div>nt        n        <!-- u05e4u05d5u05d8u05e8 -->n        <div style="background-color: #f8fafc;padding: 25px 40px;text-align: center;border-top: 1px solid #edf2f7">n            <div style="font-size: 13px;color: #718096;line-height: 1.6">n                <p style="margin: 0 0 8px 0">u05d3u05d5u05d7 u05d6u05d4 u05e0u05d5u05e6u05e8 u05d1u05d0u05d5u05e4u05df u05d0u05d5u05d8u05d5u05deu05d8u05d9 u05d5u05d0u05d9u05e0u05d5 u05deu05d4u05d5u05d5u05d4 u05d4u05deu05dcu05e6u05ea u05d4u05e9u05e7u05e2u05d4.</p>n                <p style="margin: 0">u05d9u05e9 u05dcu05d4u05eau05d9u05d9u05e2u05e5 u05e2u05dd u05d9u05d5u05e2u05e5 u05d4u05e9u05e7u05e2u05d5u05ea u05deu05d5u05e8u05e9u05d4 u05dcu05e4u05e0u05d9 u05e7u05d1u05dcu05ea u05d4u05d7u05dcu05d8u05d5u05ea u05d4u05e9u05e7u05e2u05d4.</p>n            </div>n            <div style="margin-top: 20px">n                u05e0u05d1u05e0u05d4 u05d1-u2764ufe0f u05e2"u05d9 <a href="https://www.linkedin.com/in/elay-g" style="text-decoration: none">u05e2u05d9u05dcu05d9 u05d2u05d6</a>n            </div>n        </div>n        n    </div>nnn"
      },
      "typeVersion": 1.2
    },
    {
      "id": "84a2fe62-e936-49ca-83d6-a02371e02166",
      "name": "Send Stock Analysis",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        2280,
        -100
      ],
      "webhookId": "0de4d8cd-3519-4a4a-a05b-a9c973b64141",
      "parameters": {
        "html": "={{ $json.html }}",
        "options": {},
        "subject": "=u05d4u05e1u05e7u05d9u05e8u05d4 u05d4u05d9u05d5u05deu05d9u05ea u05e9u05dc u05deu05e0u05d9u05d9u05ea {{ $('AI Agent').item.json.output.stockSymbol }}: {{ $('AI Agent').item.json.output.analysisDate }}",
        "toEmail": "={{ $('On form submission').item.json["Email:"] }}",
        "fromEmail": "Elay's AI Assistant "
      },
      "credentials": {
        "smtp": {
          "id": "583PMpoYf46gbncd",
          "name": "SMTP account"
        }
      },
      "executeOnce": false,
      "typeVersion": 2.1
    },
    {
      "id": "36943e20-b0fc-40b0-b695-e0bdbd9182d1",
      "name": "Adjust HTML Colors",
      "type": "n8n-nodes-base.code",
      "position": [
        2080,
        -100
      ],
      "parameters": {
        "jsCode": "// New function to remove topics with only one article - ultra-simple approachnfunction removeSingleArticleTopics(html) {n  // First, see if there are any topics with exactly 1 articlen  if (!html.includes('<strong>1</strong> u05deu05d0u05deu05e8u05d9u05dd')) {n    console.log('No topics with 1 article found');n    return html;n  }nn  // Find each line that contains the "u05e0u05d5u05e9u05d0" commentn  // and check if it has exactly 1 article mentionedn  const lines = html.split('\n');n  const linesToRemove = [];nn  // For each line containing "1 u05deu05d0u05deu05e8u05d9u05dd", find the topic it belongs ton  for (let i = 0; i &lt; lines.length; i++) {n    if (lines[i].includes(&#039;<strong>1</strong> u05deu05d0u05deu05e8u05d9u05dd')) {n      console.log(`Found line ${i} with 1 article mention`);n      n      // Go back to find the start of this topicn      let startLine = -1;n      for (let j = i; j &gt;= 0; j--) {n        if (lines[j].includes('&lt;!-- u05e0u05d5u05e9u05d0&#039;) || n            lines[j].includes(&#039;&lt;div style=&quot;margin-bottom: 15px; padding-bottom: 15px; border-bottom:&#039;)) {n          startLine = j;n          break;n        }n      }n      n      if (startLine === -1) {n        console.log(`Couldn&#039;t find start of topic for line ${i}`);n        continue;n      }n      n      // Go forward to find the end of this topicn      let endLine = -1;n      let divCount = 0;n      for (let j = startLine; j &lt; lines.length; j++) {n        // Count opening divsn        const openMatches = lines[j].match(/&lt;div/g);n        if (openMatches) {n          divCount += openMatches.length;n        }n        n        // Count closing divsn        const closeMatches = lines[j].match(//g);n        if (closeMatches) {n          divCount -= closeMatches.length;n        }n        n        // When divCount returns to 0, we've found the endn        if (divCount === 0 &amp;&amp; j &gt; startLine) {n          endLine = j;n          break;n        }n      }n      n      if (endLine === -1) {n        console.log(`Couldn't find end of topic for line ${i}`);n        continue;n      }n      n      // Now we have the start and end lines of the topicn      console.log(`Found topic from line ${startLine} to ${endLine}`);n      n      // Mark these lines for removaln      for (let j = startLine; j &lt;= endLine; j++) {n        linesToRemove.push(j);n      }n    }n  }n  n  // Remove the marked linesn  const newLines = [];n  for (let i = 0; i  ${getSentimentType(text)}`);n}nn// New function to remove undefined articles from HTMLnfunction removeUndefinedArticles(html) {n  // Find all article blocksn  const articleBlocksRegex = /<tr>\s*<td style="padding-bottom: 16px">\s*<table>]*&gt;[\s\S]*?\s*\s*/g;n  const articleBlocks = Array.from(html.matchAll(articleBlocksRegex));n  n  // No articles foundn  if (!articleBlocks || articleBlocks.length === 0) {n    console.log("No article blocks found");n    return html;n  }n  n  // Function to check if an article is fully undefinedn  function isFullyUndefinedArticle(articleHtml) {n    // An article is considered fully undefined if:n    // 1. It has href="undefined"n    // 2. It has link text that is "undefined"n    // 3. It has "undefined | undefined" (source and date)n    return articleHtml.includes('href="undefined"') &amp;&amp; n           articleHtml.includes('&gt;undefined</a>') &amp;&amp;n           articleHtml.includes('undefined | undefined');n  }n  n  // Identify blocks to removen  const blocksToRemove = [];n  for (const match of articleBlocks) {n    const block = match[0];n    if (isFullyUndefinedArticle(block)) {n      console.log("Found undefined article, will remove");n      blocksToRemove.push(match);n    } else {n      console.log("Found valid article, keeping it");n    }n  }n  n  // If no blocks to remove, return original HTMLn  if (blocksToRemove.length === 0) {n    console.log("No undefined articles found to remove");n    return html;n  }n  n  console.log(`Found ${blocksToRemove.length} undefined articles to remove`);n  n  // Create a new string by removing the matches from end to start (to avoid index shifting)n  let cleanedHtml = html;n  for (let i = blocksToRemove.length - 1; i &gt;= 0; i--) {n    const match = blocksToRemove[i];n    cleanedHtml = cleanedHtml.slice(0, match.index) + cleanedHtml.slice(match.index + match[0].length);n  }n  n  return cleanedHtml;n}nn// Get the HTML from the specified parameternconst html = $input.first().json.html;nlet updatedHtml = html;nn// Bug checks - check several keywordsndebugSentiment("u05d7u05d9u05d5u05d1u05d9");ndebugSentiment("u05e9u05dcu05d9u05dcu05d9");ndebugSentiment("u05e0u05d9u05d9u05d8u05e8u05dcu05d9");ndebugSentiment("u05d7u05d9u05d5u05d1u05d9-u05d7u05d6u05e7");ndebugSentiment("u05e9u05dcu05d9u05dcu05d9-u05d7u05d6u05e7");ndebugSentiment("u05d7u05d9u05d5u05d1u05d9-u05d7u05dcu05e9");ndebugSentiment("u05e9u05dcu05d9u05dcu05d9-u05d7u05dcu05e9");nn// 1. Update colors in the recommendation titlenconst titleMatch = html.match(/<h2>([^&lt;]+)/i);nif (titleMatch) {n  const titleText = titleMatch[1].trim();n  const titleSentiment = getSentimentType(titleText);n  n  // Update title colorn  updatedHtml = updatedHtml.replace(n    /(<h2>)/i,n    `$1${colors[titleSentiment].main}$2`n  );n  n  // Update side bar colorn  updatedHtml = updatedHtml.replace(n    /(<div style="position: absolute;right: 0;top: 0;bottom: 0;width: 6px">)/i,n    `$1${colors[titleSentiment].main}$2`n  );n  n  // Update gradient colorn  updatedHtml = updatedHtml.replace(n    /(<div style="position: absolute;right: 0;top: 0;width: 100%;height: 100%">)/i,n    `$1${colors[titleSentiment].gradient}$2${colors[titleSentiment].gradient.replace('0.07', '0')}$3`n  );n  n  // Update icon background colorn  updatedHtml = updatedHtml.replace(n    /(<div style="width: 40px;height: 40px;border-radius: 50%;margin-bottom: 10px;text-align: center">)/i,n    `$1${colors[titleSentiment].background}$2`n  );n}nn// 2. Update overall sentiment colornconst sentimentMatch = updatedHtml.match(/<span>([^&lt;]+)/i);nif (sentimentMatch) {n  const sentimentText = sentimentMatch[1].trim();n  const sentimentType = getSentimentType(sentimentText);n  n  updatedHtml = updatedHtml.replace(n    /(<span>)/i,n    `$1${colors[sentimentType].main}$2`n  );n}nn// 3. Update article colorsnconst articleBlocks = updatedHtml.match(/<tr>\s*<td style="padding-bottom: 16px">\s*<table>]*&gt;[\s\S]*?\s*\s*/g);nif (articleBlocks) {n  for (const block of articleBlocks) {n    // Check if this is a fully undefined article before skippingn    const isUndefined = block.includes('href="undefined"') &amp;&amp; n                        block.includes('&gt;undefined</a>') &amp;&amp; n                        block.includes('undefined | undefined');n    n    // Skip if this is a completely undefined articlen    if (isUndefined) {n      console.log("Skipping color update for undefined article");n      continue;n    }n    n    // Find sentiment within the blockn    const articleSentimentMatch = block.match(/<div>([^&lt;]+)/i);n    if (articleSentimentMatch) {n      const articleSentimentText = articleSentimentMatch[1].trim();n      const articleSentimentType = getSentimentType(articleSentimentText);n      n      // Debug check - log the identified sentimentn      debugSentiment(articleSentimentText);n      n      // Create updated blockn      let updatedBlock = block;n      n      // Update side line colorn      updatedBlock = updatedBlock.replace(n        /(<td width="4">)/i,n        `$1${colors[articleSentimentType].main}$2`n      );n      n      // Update sentiment tag colors (background and text color)n      updatedBlock = updatedBlock.replace(n        /(<div>)/i,n        `$1${colors[articleSentimentType].accent}$2${colors[articleSentimentType].main}$3`n      );n      n      // Replace the block with its updated versionn      updatedHtml = updatedHtml.replace(block, updatedBlock);n    }n  }n}nn// 4. Update recommendation button colornconst buttonMatch = updatedHtml.match(/<a>([^&lt;]+)/i);nif (buttonMatch) {n  const buttonText = buttonMatch[1].trim();n  let buttonSentiment = 'neutral'; // Defaultn  n  // Determine sentiment based on button textn  if (buttonText.includes("u05deu05deu05dcu05d9u05e5 u05dcu05e7u05e0u05d5u05ea")) {n    buttonSentiment = 'positive';n  } else if (buttonText.includes("u05deu05deu05dcu05d9u05e5 u05dcu05deu05dbu05d5u05e8")) {n    buttonSentiment = 'negative';n  } else if (buttonText.includes("u05deu05deu05dcu05d9u05e5 u05dcu05d7u05dbu05d5u05ea")) {n    buttonSentiment = 'neutral';n  }n  n  // Update button background colorn  updatedHtml = updatedHtml.replace(n    /(<a>)/i,n    `$1${colors[buttonSentiment].main}$2`n  );n  n  // Update box-shadow colorn  const boxShadowRgba = `rgba(${parseInt(colors[buttonSentiment].main.substring(1, 3), 16)}, ${parseInt(colors[buttonSentiment].main.substring(3, 5), 16)}, ${parseInt(colors[buttonSentiment].main.substring(5, 7), 16)}, 0.25)`;n  updatedHtml = updatedHtml.replace(n    /(box-shadow: 0 4px 6px )rgba\([^)]+\)(;[^"]*"&gt;)/i,n    `$1${boxShadowRgba}$2`n  );n}nn// 5. Remove undefined articlesnupdatedHtml = removeUndefinedArticles(updatedHtml);nn// 6. Remove topics with only one articlenupdatedHtml = removeSingleArticleTopics(updatedHtml);nn// Return updated HTMLnreturn { html: updatedHtml };"
      },
      "typeVersion": 2
    },
    {
      "id": "d9174ea1-e42b-4533-98ab-9dc8f94055db",
      "name": "Think",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "position": [
        1680,
        140
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "ca2820e9-553d-477b-9084-74b2fab92cc9",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        940,
        260
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace OpenAI Credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "2e0013ca-2dda-425c-b6d8-bdd3b3cd262d",
      "name": "Generate Variables For API",
      "type": "n8n-nodes-base.code",
      "position": [
        2760,
        -20
      ],
      "parameters": {
        "jsCode": "// Function to generate yesterday's date in the required formatnfunction getYesterdayDateFormat() {n  // Create a current date objectn  const today = new Date();n  n  // Set the date to the previous day (yesterday)n  today.setDate(today.getDate() - 1);n  n  // Reset hours, minutes, seconds and milliseconds to 00:00:00.000n  today.setHours(0, 0, 0, 0);n  n  // Extract componentsn  const year = today.getFullYear();n  const month = String(today.getMonth() + 1).padStart(2, '0'); // Months in JS start from 0n  const day = String(today.getDate()).padStart(2, '0');n  const hours = String(today.getHours()).padStart(2, '0');n  const minutes = String(today.getMinutes()).padStart(2, '0');n  n  // Build the string in the required formatn  return `${year}${month}${day}T${hours}${minutes}`;n}n// Calculate the datenconst yesterdayDate = getYesterdayDateFormat();n// Return the result in the format required by n8n - array of objectsnreturn [n  {n    json: {n      wanted_date: yesterdayDaten    }n  }n];"
      },
      "typeVersion": 2
    },
    {
      "id": "a3d8d689-7b9a-4d45-9a9b-ffb9597606a1",
      "name": "Set Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        2920,
        -20
      ],
      "parameters": {
        "values": {
          "number": [
            {
              "name": "wantedDate",
              "value": "={{ $json.wanted_date }}"
            }
          ],
          "string": [
            {
              "name": "stockSymbol",
              "value": "={{ $('Workflow Input Trigger').item.json.ticker }}"
            },
            {
              "name": "apikey"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "f4eeb758-ba3e-4fb2-882f-7422bdcdc30b",
      "name": "Get News Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3100,
        -20
      ],
      "parameters": {
        "url": "=https://www.alphavantage.co/query?function=NEWS_SENTIMENT&amp;tickers={{ $json.stockSymbol }}&amp;sort=RELEVANCE&amp;time_from={{ $json.wantedDate }}&amp;apikey={{ $json.apikey }}",
        "options": {}
      },
      "typeVersion": 4.1
    },
    {
      "id": "87a2eb36-36e2-427d-8db2-2de3a280e404",
      "name": "Analyse API Input",
      "type": "n8n-nodes-base.code",
      "position": [
        3280,
        -20
      ],
      "parameters": {
        "jsCode": "/**n * Custom code for n8n Code node to analyze news data from Alpha Vantagen * n * - The code receives API data from the previous noden * - Analyzes sentiment, leading articles, and hot topicsn * - Returns a structured JSON object for further processingn */nnconst stockSymbol = $('Set Variables').first().json.stockSymbolnconst allNews = $input.first().json.feedn  ;nconst today = new Date().toISOString().split('T')[0]; // Current date in YYYY-MM-DD formatnn// Filter articles relevant to the stocknconst relevantArticles = allNews.filter(article =&gt; {n  return article.ticker_sentiment &amp;&amp; article.ticker_sentiment.some(ticker =&gt; n    ticker.ticker === stockSymboln  );n});nn// Sentiment analysisnlet sentimentCounts = {n  "Bullish": 0,n  "Somewhat-Bullish": 0,n  "Neutral": 0,n  "Somewhat-Bearish": 0,n  "Bearish": 0n};nnlet totalSentimentScore = 0;nlet totalRelevanceScore = 0;nnrelevantArticles.forEach(article =&gt; {n  const stockTicker = article.ticker_sentiment.find(ticker =&gt; ticker.ticker === stockSymbol);n  if (stockTicker) {n    sentimentCounts[stockTicker.ticker_sentiment_label]++;n    totalSentimentScore += parseFloat(stockTicker.ticker_sentiment_score) * parseFloat(stockTicker.relevance_score);n    totalRelevanceScore += parseFloat(stockTicker.relevance_score);n  }n});nnconst avgSentimentScore = totalRelevanceScore &gt; 0 ? totalSentimentScore / totalRelevanceScore : 0;nn// Determining overall sentimentnlet overallSentiment;nif (avgSentimentScore &gt;= 0.35) {n  overallSentiment = "u05d7u05d9u05d5u05d1u05d9 u05deu05d0u05d5u05d3";n} else if (avgSentimentScore &gt;= 0.15) {n  overallSentiment = "u05d7u05d9u05d5u05d1u05d9";n} else if (avgSentimentScore &gt; -0.15) {n  overallSentiment = "u05e0u05d9u05d9u05d8u05e8u05dcu05d9";n} else if (avgSentimentScore &gt; -0.35) {n  overallSentiment = "u05e9u05dcu05d9u05dcu05d9";n} else {n  overallSentiment = "u05e9u05dcu05d9u05dcu05d9 u05deu05d0u05d5u05d3";n}nn// Most influential articlesnconst topArticles = relevantArticlesn  .map(article =&gt; {n    const stockTicker = article.ticker_sentiment.find(ticker =&gt; ticker.ticker === stockSymbol);n    return {n      title: article.title,n      url: article.url,n      source: article.source,n      date: formatDate(article.time_published),n      sentiment_label: stockTicker ? stockTicker.ticker_sentiment_label : "N/A",n      sentiment_score: stockTicker ? parseFloat(stockTicker.ticker_sentiment_score) : 0,n      relevance_score: stockTicker ? parseFloat(stockTicker.relevance_score) : 0,n      impact_score: stockTicker ? Math.abs(parseFloat(stockTicker.ticker_sentiment_score) * parseFloat(stockTicker.relevance_score)) : 0n    };n  })n  .sort((a, b) =&gt; b.impact_score - a.impact_score)n  .slice(0, 5);nn// Analysis of main topicsnconst topicsMap = {};nnrelevantArticles.forEach(article =&gt; {n  if (article.topics) {n    article.topics.forEach(topic =&gt; {n      if (!topicsMap[topic.topic]) {n        topicsMap[topic.topic] = {n          count: 0,n          relevance: 0n        };n      }n      topicsMap[topic.topic].count++;n      topicsMap[topic.topic].relevance += parseFloat(topic.relevance_score);n    });n  }n});nnconst hotTopics = Object.entries(topicsMap)n  .map(([topic, data]) =&gt; ({n    topic,n    article_count: data.count,n    average_relevance: (data.relevance / data.count).toFixed(2)n  }))n  .sort((a, b) =&gt; b.article_count - a.article_count)n  .slice(0, 5);nn// Creating result objectnconst analysisResult = {n  stock_symbol: stockSymbol,n  analysis_date: today,n  sentiment_analysis: {n    overall_sentiment: overallSentiment,n    sentiment_score: parseFloat(avgSentimentScore.toFixed(4)),n    sentiment_distribution: sentimentCountsn  },n  top_articles: topArticles.map(article =&gt; ({n    title: article.title,n    source: article.source,n    url: article.url,n    date: article.date,n    sentiment: article.sentiment_label,n    impact_score: article.impact_score.toFixed(4)n  })),n  hot_topics: hotTopics,n  recent_trends: {n    description: getTrendDescription(overallSentiment, hotTopics),n    market_outlook: getMarketOutlook(overallSentiment)n  }n};nn// Helper functionsnfunction formatDate(dateStr) {n  if (!dateStr) return "N/A";n  n  try {n    // Format: 20250418T152049 -&gt; 2025-04-18n    const year = dateStr.substring(0, 4);n    const month = dateStr.substring(4, 6);n    const day = dateStr.substring(6, 8);n    return `${year}-${month}-${day}`;n  } catch (e) {n    return dateStr;n  }n}nnfunction getTrendDescription(sentiment, topics) {n  let description = "";n  n  if (sentiment === "u05d7u05d9u05d5u05d1u05d9 u05deu05d0u05d5u05d3" || sentiment === "u05d7u05d9u05d5u05d1u05d9") {n    description = "u05deu05d2u05deu05d4 u05d7u05d9u05d5u05d1u05d9u05ea u05dbu05d0u05e9u05e8 u05deu05e9u05e7u05d9u05e2u05d9u05dd u05deu05eau05deu05e7u05d3u05d9u05dd u05d1u05e2u05d9u05e7u05e8 u05d1";n  } else if (sentiment === "u05e9u05dcu05d9u05dcu05d9 u05deu05d0u05d5u05d3" || sentiment === "u05e9u05dcu05d9u05dcu05d9") {n    description = "u05deu05d2u05deu05d4 u05e9u05dcu05d9u05dcu05d9u05ea u05dbu05d0u05e9u05e8 u05d4u05d7u05e9u05e9u05d5u05ea u05d4u05e2u05d9u05e7u05e8u05d9u05d9u05dd u05deu05eau05deu05e7u05d3u05d9u05dd u05d1";n  } else {n    description = "u05deu05d2u05deu05d4 u05deu05e2u05d5u05e8u05d1u05ea u05e2u05dd u05d4u05eau05deu05e7u05d3u05d5u05ea u05d1";n  }n  n  if (topics.length &gt; 0) {n    const topThreeTopics = topics.slice(0, Math.min(3, topics.length));n    description += topThreeTopics.map(t =&gt; t.topic).join(", ");n  } else {n    description += "u05deu05d2u05d5u05d5u05df u05e0u05d5u05e9u05d0u05d9u05dd";n  }n  n  return description + ".";n}nnfunction getMarketOutlook(sentiment) {n  if (sentiment === "u05d7u05d9u05d5u05d1u05d9 u05deu05d0u05d5u05d3") {n    return "u05eau05d7u05d6u05d9u05ea u05e9u05d5u05e7 u05d7u05d9u05d5u05d1u05d9u05ea u05deu05d0u05d5u05d3. u05d4u05e1u05e0u05d8u05d9u05deu05e0u05d8 u05d4u05dbu05dcu05dcu05d9 u05deu05e6u05d1u05d9u05e2 u05e2u05dc u05d0u05deu05d5u05df u05deu05e9u05e7u05d9u05e2u05d9u05dd u05d2u05d1u05d5u05d4 u05d5u05e4u05d5u05d8u05e0u05e6u05d9u05d0u05dc u05dcu05e2u05dcu05d9u05d9u05d4 u05d1u05d8u05d5u05d5u05d7 u05d4u05e7u05e6u05e8.";n  } else if (sentiment === "u05d7u05d9u05d5u05d1u05d9") {n    return "u05eau05d7u05d6u05d9u05ea u05e9u05d5u05e7 u05d7u05d9u05d5u05d1u05d9u05ea. u05d9u05e9u05e0u05df u05d0u05d9u05e0u05d3u05d9u05e7u05e6u05d9u05d5u05ea u05dcu05d0u05d5u05e4u05d8u05d9u05deu05d9u05d5u05ea u05d6u05d4u05d9u05e8u05d4 u05d1u05e7u05e8u05d1 u05deu05e9u05e7u05d9u05e2u05d9u05dd.";n  } else if (sentiment === "u05e0u05d9u05d9u05d8u05e8u05dcu05d9") {n    return "u05eau05d7u05d6u05d9u05ea u05e9u05d5u05e7 u05deu05e2u05d5u05e8u05d1u05ea. u05e7u05d9u05d9u05deu05d9u05dd u05dbu05d5u05d7u05d5u05ea u05deu05d0u05d6u05e0u05d9u05dd u05e9u05dc u05d0u05d5u05e4u05d8u05d9u05deu05d9u05d5u05ea u05d5u05e4u05e1u05d9u05deu05d9u05d5u05ea u05d1u05e9u05d5u05e7.";n  } else if (sentiment === "u05e9u05dcu05d9u05dcu05d9") {n    return "u05eau05d7u05d6u05d9u05ea u05e9u05d5u05e7 u05e9u05dcu05d9u05dcu05d9u05ea. u05d9u05e9u05e0u05df u05d3u05d0u05d2u05d5u05ea u05d1u05e7u05e8u05d1 u05deu05e9u05e7u05d9u05e2u05d9u05dd u05e9u05e2u05e9u05d5u05d9u05d5u05ea u05dcu05d4u05e9u05e4u05d9u05e2 u05e2u05dc u05d4u05deu05e0u05d9u05d4 u05d1u05d8u05d5u05d5u05d7 u05d4u05e7u05e6u05e8.";n  } else {n    return "u05eau05d7u05d6u05d9u05ea u05e9u05d5u05e7 u05e9u05dcu05d9u05dcu05d9u05ea u05deu05d0u05d5u05d3. u05e7u05d9u05d9u05deu05ea u05d0u05d5u05d5u05d9u05e8u05ea u05d6u05d4u05d9u05e8u05d5u05ea u05deu05e9u05deu05e2u05d5u05eau05d9u05ea u05d5u05e0u05d8u05d9u05d9u05d4 u05dcu05deu05dbu05d9u05e8u05d5u05ea.";n  }n}nn// Return the object for further flow in n8nnreturn {n  json: analysisResultn};"
      },
      "typeVersion": 2
    },
    {
      "id": "8a108780-d2e3-4cc7-bf7f-49da726f37fd",
      "name": "Workflow Input Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        740,
        800
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "ticker"
            },
            {
              "name": "chart_style"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8491ca61-2367-401e-9ff2-4f1d90f3ce59",
      "name": "Download Chart",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1540,
        520
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "1250dca0-d4d6-4890-9aa4-110cd0f0fbb6",
      "name": "Get Chart URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1320,
        520
      ],
      "parameters": {
        "url": "https://api.chart-img.com/v2/tradingview/advanced-chart/storage",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "jsonBody": "={n  "style": "candle",n  "theme": "light",n  "interval": "1W",n  "symbol": "NASDAQ:{{ $json.ticker }}",n  "override": {n    "showStudyLastValue": falsen  },n  "studies": [n    {n      "name": "Volume",n      "forceOverlay": truen    },n    {n      "name": "Moving Average Exponential",n      "inputs": {n        "length": 200n      }n    },n    {n      "name": "Relative Strength Index"n    }n  ]n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "cnQIlBI286n0AZiU",
          "name": "Header Auth account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "cfc9c470-c284-4d58-b6be-260f36d3d2b7",
      "name": "Get Price History",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1320,
        800
      ],
      "parameters": {
        "url": "=https://api.twelvedata.com/time_series",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "symbol",
              "value": "={{ $json.ticker }}"
            },
            {
              "name": "interval",
              "value": "1day"
            },
            {
              "name": "outputsize",
              "value": "180"
            },
            {
              "name": "apikey",
              "value": "={{ $json.TwelveData_API_Key }}"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "3974f7f8-99b3-43b2-83f3-05819cdde7b2",
      "name": "Get Bollinger Bands",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1320,
        960
      ],
      "parameters": {
        "url": "=https://api.twelvedata.com/bbands",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "symbol",
              "value": "={{ $json.ticker }}"
            },
            {
              "name": "interval",
              "value": "1day"
            },
            {
              "name": "outputsize",
              "value": "1"
            },
            {
              "name": "apikey",
              "value": "={{ $json.TwelveData_API_Key }}"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "0d333729-3fe5-4253-9989-16adaf1166b8",
      "name": "Get MACD",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1320,
        1120
      ],
      "parameters": {
        "url": "=https://api.twelvedata.com/macd",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "symbol",
              "value": "={{ $json.ticker }}"
            },
            {
              "name": "interval",
              "value": "1day"
            },
            {
              "name": "outputsize",
              "value": "1"
            },
            {
              "name": "apikey",
              "value": "={{ $json.TwelveData_API_Key }}"
            }
          ]
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "4bd10a52-082b-4842-91ee-ef748c6ba695",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1820,
        960
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.1
    },
    {
      "id": "8061fbcf-d138-44b5-b6d7-14c7a4e5904e",
      "name": "Calculate Support Resistance",
      "type": "n8n-nodes-base.code",
      "position": [
        1540,
        800
      ],
      "parameters": {
        "jsCode": "// Get historical price datanconst data = $input.item.json;nn// Check if data existsnif (!data.values || data.values.length === 0) {n  return { json: { error: "No price data available", ticker: data.meta?.symbol } };n}nn// Convert prices to numbersnconst prices = data.values.map(v =&gt; parseFloat(v.close)).reverse();nn// Function to calculate Fibonacci levelsnfunction calculateFibonacciLevels() {n  // Find min and max pricesn  const max = Math.max(...prices);n  const min = Math.min(...prices);n  const diff = max - min;n  n  return {n    level_0: min.toFixed(2),n    level_0_236: (min + diff * 0.236).toFixed(2),n    level_0_382: (min + diff * 0.382).toFixed(2),n    level_0_5: (min + diff * 0.5).toFixed(2),n    level_0_618: (min + diff * 0.618).toFixed(2),n    level_0_786: (min + diff * 0.786).toFixed(2),n    level_1: max.toFixed(2)n  };n}n// Function to identify support and resistance levelsnfunction findSupportResistanceLevels() {n  // We need at least 30 data pointsn  if (prices.length &lt; 30) {n    return { support: [], resistance: [] };n  }n  n  const supportLevels = [];n  const resistanceLevels = [];n  n  // Check each point (except edges) if it&#039;s a local minimum or maximumn  const lookback = 5; // how many points to check in each directionn  n  for (let i = lookback; i &lt; prices.length - lookback; i++) {n    // Check for local minimum (support)n    let isMinimum = true;n    for (let j = i - lookback; j &lt; i; j++) {n      if (prices[j] &lt;= prices[i]) {n        isMinimum = false;n        break;n      }n    }n    n    for (let j = i + 1; j &lt;= i + lookback; j++) {n      if (prices[j] &lt;= prices[i]) {n        isMinimum = false;n        break;n      }n    }n    n    if (isMinimum) {n      supportLevels.push(prices[i]);n    }n    n    // Check for local maximum (resistance)n    let isMaximum = true;n    for (let j = i - lookback; j <i>= prices[i]) {n        isMaximum = false;n        break;n      }n    }n    n    for (let j = i + 1; j = prices[i]) {n        isMaximum = false;n        break;n      }n    }n    n    if (isMaximum) {n      resistanceLevels.push(prices[i]);n    }n  }n  n  // Sort and remove duplicatesn  const uniqueSupports = [...new Set(supportLevels)];n  const uniqueResistances = [...new Set(resistanceLevels)];n  n  // Return only significant levels (up to 5 of each)n  return {n    support: uniqueSupports.sort((a, b) =&gt; b - a).slice(0, 5).map(p =&gt; p.toFixed(2)),n    resistance: uniqueResistances.sort((a, b) =&gt; a - b).slice(0, 5).map(p =&gt; p.toFixed(2))n  };n}nn// Calculate levelsnconst fibonacciLevels = calculateFibonacciLevels();nconst supportResistanceLevels = findSupportResistanceLevels();nn// Return information with additional stock datanreturn {n  json: {n    ticker: data.meta.symbol,n    currentPrice: parseFloat(data.values[0].close).toFixed(2),n    fibonacci: fibonacciLevels,n    supportResistance: supportResistanceLevels,n    dataPoints: prices.lengthn  }n};"
      },
      "typeVersion": 2
    },
    {
      "id": "c692581d-a41d-48ef-9a7a-0a20fbceea81",
      "name": "Organizing Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2040,
        960
      ],
      "parameters": {
        "jsCode": "// Getting data from different sourcesn// Checking existence of objects before trying to access themnconst items = $input.all();nconst fibData = $input.first().json;nn// Trying to locate bband and MACD data if they existnlet bbandsData = null;nlet macdData = null;nn// Trying to check if there is data in additional itemsnif (items.length &gt; 1 &amp;&amp; items[1] &amp;&amp; items[1].json) {n  bbandsData = items[1].json;n}nnif (items.length &gt; 2 &amp;&amp; items[2] &amp;&amp; items[2].json) {n  macdData = items[2].json;n}nn// Creating data structure for the response - ensure all fields existnconst result = {n  ticker: fibData.ticker || "u05dcu05d0 u05d9u05d3u05d5u05e2",n  currentPrice: fibData.currentPrice || "0",n  timestamp: new Date().toISOString(),n  technicalAnalysis: {n    fibonacci: fibData.fibonacci || {},n    supportResistance: fibData.supportResistance || { support: [], resistance: [] },n    bollingerBands: {},n    macd: {}n  }n};nn// Adding Bollinger Bands data - only if they existnif (bbandsData &amp;&amp; bbandsData.values &amp;&amp; bbandsData.values.length &gt; 0) {n  const bbands = bbandsData.values[0];n  result.technicalAnalysis.bollingerBands = {n    upperBand: parseFloat(bbands.upper_band).toFixed(2),n    middleBand: parseFloat(bbands.middle_band).toFixed(2),n    lowerBand: parseFloat(bbands.lower_band).toFixed(2)n  };n} else if (bbandsData &amp;&amp; bbandsData.status === "ok") {n  // If returning another data formatn  result.technicalAnalysis.bollingerBands = {n    upperBand: bbandsData.upperBand || bbandsData.upper_band || "0",n    middleBand: bbandsData.middleBand || bbandsData.middle_band || "0",n    lowerBand: bbandsData.lowerBand || bbandsData.lower_band || "0"n  };n}nn// Adding MACD data - only if they existnif (macdData &amp;&amp; macdData.values &amp;&amp; macdData.values.length &gt; 0) {n  const macd = macdData.values[0];n  result.technicalAnalysis.macd = {n    macd: parseFloat(macd.macd).toFixed(2),n    signal: parseFloat(macd.signal).toFixed(2),n    histogram: parseFloat(macd.hist).toFixed(2)n  };n} else if (macdData &amp;&amp; macdData.status === "ok") {n  // If returning another data formatn  result.technicalAnalysis.macd = {n    macd: macdData.macd || "0",n    signal: macdData.signal || "0",n    histogram: macdData.histogram || macdData.hist || "0"n  };n}nn// Creating summary and recommendationnlet bullishFactors = [];nlet bearishFactors = [];nn// Analyzing Bollinger Bands - only if data existsnconst bbands = result.technicalAnalysis.bollingerBands;nif (bbands.upperBand &amp;&amp; bbands.lowerBand) {n  const currentPrice = parseFloat(result.currentPrice);n  const upperBand = parseFloat(bbands.upperBand);n  const lowerBand = parseFloat(bbands.lowerBand);n  n  if (!isNaN(currentPrice) &amp;&amp; !isNaN(upperBand) &amp;&amp; !isNaN(lowerBand)) {n    if (currentPrice &gt; upperBand) {n      bearishFactors.push("u05deu05d7u05d9u05e8 u05deu05e2u05dc u05e8u05e6u05d5u05e2u05ea u05d1u05d5u05dcu05d9u05e0u05d2u05e8 u05d4u05e2u05dcu05d9u05d5u05e0u05d4 - u05d0u05e4u05e9u05e8u05d5u05ea u05dcu05e7u05e0u05d9u05d9u05d4 u05d9u05eau05e8");n    } else if (currentPrice  signal) {n      bullishFactors.push("MACD u05deu05e2u05dc u05e7u05d5 u05d4u05d0u05d9u05eau05d5u05ea - u05d0u05d9u05e0u05d3u05d9u05e7u05e6u05d9u05d4 u05d7u05d9u05d5u05d1u05d9u05ea");n    } else {n      bearishFactors.push("MACD u05deu05eau05d7u05ea u05dcu05e7u05d5 u05d4u05d0u05d9u05eau05d5u05ea - u05d0u05d9u05e0u05d3u05d9u05e7u05e6u05d9u05d4 u05e9u05dcu05d9u05dcu05d9u05ea");n    }n  }n}nn// Analyzing support and resistance levels - only if data existsnconst supportResistance = result.technicalAnalysis.supportResistance;nif (supportResistance.support &amp;&amp; supportResistance.resistance) {n  const currentPrice = parseFloat(result.currentPrice);n  n  if (!isNaN(currentPrice)) {n    const supports = supportResistance.support.map(s =&gt; parseFloat(s)).filter(s =&gt; !isNaN(s));n    const resistances = supportResistance.resistance.map(r =&gt; parseFloat(r)).filter(r =&gt; !isNaN(r));n    n    // Finding the closest support leveln    let closestSupport = null;n    let minSupportDist = Infinity;n    for (const support of supports) {n      if (support &lt; currentPrice) {n        const dist = currentPrice - support;n        if (dist  currentPrice) {n        const dist = resistance - currentPrice;n        if (dist &lt; minResistanceDist) {n          minResistanceDist = dist;n          closestResistance = resistance;n        }n      }n    }n    n    // Adding support/resistance analysisn    if (closestSupport !== null) {n      const supportPercentage = ((currentPrice - closestSupport) / currentPrice * 100).toFixed(2);n      if (supportPercentage &lt; 5) {n        bullishFactors.push(`u05d4u05deu05d7u05d9u05e8 u05e7u05e8u05d5u05d1 u05dcu05e8u05deu05ea u05eau05deu05d9u05dbu05d4 (${supportPercentage}%) - u05d0u05e4u05e9u05e8u05d5u05ea u05dcu05d4u05d9u05e4u05d5u05da u05dbu05dcu05e4u05d9 u05deu05e2u05dcu05d4`);n      }n    }n    n    if (closestResistance !== null) {n      const resistancePercentage = ((closestResistance - currentPrice) / currentPrice * 100).toFixed(2);n      if (resistancePercentage  0) {n  const currentPrice = parseFloat(result.currentPrice);n  n  if (!isNaN(currentPrice)) {n    const fibLevels = Object.values(fibonacci).map(level =&gt; parseFloat(level)).filter(level =&gt; !isNaN(level));n    fibLevels.sort((a, b) =&gt; a - b);n    n    // Checking which Fibonacci level the price is atn    for (let i = 0; i = fibLevels[i] &amp;&amp; currentPrice &lt;= fibLevels[i+1]) {n        // If the price is close to a Fibonacci resistance leveln        if (Math.abs(currentPrice - fibLevels[i+1]) / currentPrice * 100 &lt; 2) {n          bearishFactors.push(`u05d4u05deu05d7u05d9u05e8 u05e7u05e8u05d5u05d1 u05dcu05e8u05deu05ea u05e4u05d9u05d1u05d5u05e0u05d0u05e6&#039;u05d9 ${[0, 23.6, 38.2, 50, 61.8, 78.6, 100][Math.min(i+1, 6)]}% - u05d0u05e4u05e9u05e8u05d5u05ea u05dcu05d4u05eau05e0u05d2u05d3u05d5u05ea`);n        }n        // If the price is close to a Fibonacci support leveln        if (Math.abs(currentPrice - fibLevels[i]) / currentPrice * 100  bearishFactors.length) {n  recommendation = "u05d7u05d9u05d5u05d1u05d9u05ea";n} else if (bearishFactors.length &gt; bullishFactors.length) {n  recommendation = "u05e9u05dcu05d9u05dcu05d9u05ea";n} else {n  recommendation = "u05e0u05d9u05d9u05d8u05e8u05dcu05d9u05ea";n}nn// Adding summary to the resultnresult.summary = {n  recommendation: recommendation,n  bullishFactors: bullishFactors,n  bearishFactors: bearishFactorsn};nnreturn { json: result };"
      },
      "typeVersion": 2
    },
    {
      "id": "d00b380b-43a4-478e-8265-d79299278867",
      "name": "Merge-2",
      "type": "n8n-nodes-base.merge",
      "position": [
        2440,
        800
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.1
    },
    {
      "id": "4ca4c3aa-9c91-4a6c-973f-bb0ed3754a82",
      "name": "ChatGPT 4o",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2900,
        800
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "# RolenYou are a senior technical analyst who merges visual insights with quantitative indicators.nn# Inputsn1. Visual JSON from Agent 1:n   {n     "ai_agent_visual_analysis": "..."n   }n2. Technical-indicator JSON in the format:n   {n     "ticker": "...",n     "currentPrice": "...",n     "timestamp": "...",n     "technicalAnalysis": {n       "fibonacci": { ... },n       "supportResistance": { ... },n       "bollingerBands": { ... },n       "macd": { ... }n     },n     "summary": { ... }n   }nn# Expected SectionsnWrite five titled sections exactly in this order:nn1. Quick Stats  n   - Ticker, current price, timestamp  n   - Overall recommendation from technical JSON, if presentnn2. Candles and EMA  n   - Use Agent 1 data: trendDirection, candlestickPatterns, emaRelation, volumeNotesnn3. RSI  n   - Report rsiNumeric and rsiState from Agent 1  n   - Mention rsiDivergence and its implicationnn4. Indicator Synthesis  n   - Fibonacci u2013 cite closest level above and below price  n   - Bollinger Bands u2013 quote upper, middle, lower and note price position  n   - MACD u2013 quote macd, signal, histogram, note cross or momentum if numbers are valid  n   - Support-Resistance u2013 use technicalAnalysis plus priceZones from Agent 1 to highlight the nearest levelsnn5. Actionable Takeaway  n   - One sentence bias (bullish, bearish, neutral)  n   - Clear next step such as watch for break above X or pullback to Ynn# Style Rulesn- Be concise and strictly data driven  n- Every statement must reference either a value from the inputs or a specific visual observation from Agent 1  n- No speculation beyond supplied data  n- End after the Takeaway section u2013 output nothing else"
            },
            {
              "content": "={{ $json.textPayload }}"
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "2m1HH5crgPAhTJlv",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "d46f175b-0737-4e33-b8fc-4937f0c6456e",
      "name": "Set Variable",
      "type": "n8n-nodes-base.set",
      "position": [
        2040,
        520
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fdf7e016-7082-4146-9038-454139023990",
              "name": "ai_agent_visual_analysis",
              "type": "string",
              "value": "={{ $('First Technical Analysis').item.json.choices[0].message.content }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "186b6551-ac08-43f3-b000-9be984a4eb13",
      "name": "Warp as JSON for GPT",
      "type": "n8n-nodes-base.code",
      "position": [
        2660,
        800
      ],
      "parameters": {
        "jsCode": "/**n * INPUT: items[0].json (Original JSON)n * OUTPUT: { textPayload: "```json\n{ ... }\n```" }n */nnconst pretty = JSON.stringify(items[0].json, null, 2);nconst wrapped = `\`\`\`json\n${pretty}\n\`\`\``;nnreturn [n  {n    json: {n      textPayload: wrappedn    }n  }n];n"
      },
      "typeVersion": 2
    },
    {
      "id": "b42da048-4e0a-4e45-b6a4-9272473844cb",
      "name": "Set Final Response",
      "type": "n8n-nodes-base.set",
      "position": [
        3280,
        800
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fdf7e016-7082-4146-9038-454139023990",
              "name": "response",
              "type": "string",
              "value": "={{ $json.message.content }}"
            },
            {
              "id": "4e5afd49-67c2-40ab-bc8c-565dea3850ed",
              "name": "image",
              "type": "string",
              "value": "={{ $('Download Chart').item.json.url }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c718d0a7-2689-42da-985f-17030583e51c",
      "name": "Set Stock Symbol and API Key",
      "type": "n8n-nodes-base.set",
      "position": [
        960,
        800
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cf5f7210-5b54-4f4a-abf7-87873be82df4",
              "name": "ticker",
              "type": "string",
              "value": "={{ $json.ticker }}"
            },
            {
              "id": "9f008c4b-60e2-4d99-a119-b0170ec28358",
              "name": "TwelveData_API_Key",
              "type": "string",
              "value": ""
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "884a7e3b-3e8f-4c69-8950-5b0f1dd25f29",
      "name": "First Technical Analysis",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1820,
        520
      ],
      "parameters": {
        "text": "=# RolenYou are a visual chart analyst.  nYour only input is a weekly candlestick chart image that shows:n- Price candles and volume bars  n- One short-term EMA line  n- An RSI panel with its live value  nn# TasknInspect the image and produce a **structured JSON** object with the following keys:nn{n  "rsiNumeric": number,          // exact RSI value from the chartn  "rsiState": "overbought" | "oversold" | "neutral",n  "rsiDivergence": "bullish" | "bearish" | "none",n  "trendDirection": "up" | "down" | "sideways",n  "candlestickPatterns": [ "pattern1", "pattern2", ... ],   // max 3n  "emaRelation": "aboveEMA" | "belowEMA" | "testingEMA",n  "volumeNotes": "string",        // brief comment on recent volume behaviorn  "priceZones": {                 // visually inferred areasn      "potentialSupport": [number, ...],  // up to 2 levels taken from visible lowsn      "potentialResistance": [number, ...]// up to 2 levels taken from visible highsn  }n}nn# Style Rulesn- Derive every value only from what is visible in the chartn- Do not mention any external data or speculationn- Return the JSON object only, nothing elsen",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {
          "detail": "auto"
        },
        "resource": "image",
        "simplify": false,
        "inputType": "base64",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "id": "2m1HH5crgPAhTJlv",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "ba7aca23-5d4c-4bfd-8d7f-af45aaa8d8a0",
      "name": "Schedule Trigger1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        2560,
        -20
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4b93b4ba-3369-4051-a92d-d3ff811fb566",
      "name": "Technical Analysis Tool",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        1360,
        140
      ],
      "parameters": {
        "name": "technical_analysis",
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "GDXsoM9kWq3cz53Y",
          "cachedResultName": "technical_analysis"
        },
        "description": "Call this tool to get an analysis of a requested stock. It'll be obligatory to pass ticker.",
        "workflowInputs": {
          "value": {
            "ticker": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('ticker', ``, 'string') }}"
          },
          "schema": [
            {
              "id": "ticker",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ticker",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "chart_style",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "chart_style",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "typeVersion": 2
    },
    {
      "id": "c5d70195-f90b-42b4-b056-52794c75c20f",
      "name": "Trends Analysis Tool",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        1520,
        140
      ],
      "parameters": {
        "name": "trends_analysis",
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "jnlklBcNkky9yFoc",
          "cachedResultName": "trends_analysis"
        },
        "description": "Call this tool to get an analysis of a requested stock. It'll be obligatory to pass ticker.",
        "workflowInputs": {
          "value": {
            "ticker": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('ticker', ``, 'string') }}"
          },
          "schema": [
            {
              "id": "ticker",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ticker",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "chart_style",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "chart_style",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "typeVersion": 2
    },
    {
      "id": "de8355ea-8f6b-4733-b5ac-06e080e42e30",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2900,
        120
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace Alphavantage API Key"
      },
      "typeVersion": 1
    },
    {
      "id": "9c25c2ab-796f-4156-8267-efe6d0182e9d",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1800,
        680
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace OpenAI Credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "e78394cb-809e-4731-b74b-e8378f8e2bc9",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2900,
        920
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace OpenAI Credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "dcf46ba4-b309-4d41-8041-717d564c0690",
      "name": "Sticky Note17",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1300,
        680
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace Chart-img API Key"
      },
      "typeVersion": 1
    },
    {
      "id": "727d5d8b-c537-41d2-a757-479813ecb733",
      "name": "Sticky Note19",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        920,
        980
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace TwelveData API Key"
      },
      "typeVersion": 1
    },
    {
      "id": "580f36fb-2d85-4a74-825b-540f328b860f",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2280,
        60
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 80,
        "content": "### Replace SMTP Credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "e40b611a-12c3-4975-b692-f338d0477c8b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        -220
      ],
      "parameters": {
        "color": 7,
        "width": 440,
        "height": 300,
        "content": "# Advance Stock Analysis (both Technical and Trends) Using GPT4o Powered AI Agentnn## Built by  [Elay Guez](https://www.linkedin.com/in/elay-g)"
      },
      "typeVersion": 1
    },
    {
      "id": "ab83de34-3083-4882-b329-c368d5818917",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        100
      ],
      "parameters": {
        "color": 7,
        "width": 440,
        "height": 1200,
        "content": "### Overview ###nnGet comprehensive stock analysis with this AI-powered workflow that provides actionable insights for your investment decisions. On a weekly basis, this workflow:nn- Analyzes stock data from multiple sources (Chart-img, Twelve Data API, Alphavantage)n- Performs technical analysis using advanced indicators (RSI, MACD, Bollinger Bands, Resistance andu00a0Supportu00a0Levels)n- Scans financial news from Alpha Vantage to capture market sentimentn- Uses OpenAI's GPT-4o to identify patterns, trends, and trading opportunitiesn- Generates a fully styled, responsive HTML email (with proper RTL layout) in Hebrewn- Sends detailed recommendations directly to your inboxnn**Perfect for investors, traders, and financial analysts who want data-driven stock insights - combining technical indicators with news sentiment for more informed decisions.**nn### Setup Instructions ###nn**Estimated setup time:**n- 15 minutesnn**Required credentials:**n- OpenAI API Keyn- Chart-img API Key (free tier)n- Twelve Data API Key (free tier)n- Alpha Vantage API Key (free tier)n- SMTP credentials (for email delivery)nn**Steps:**nn1. Import this template into your n8n instance.n2. Add your API keys under credentials.n3. Configure the SMTP Email node with: Host (e.g., smtp.gmail.com), Port (465 or 587), Username (your email), Password (app-specific password or login).n4. Activate the workflow.n5. Fill in the Form.n6. **Enjoy!** (Check your Spam mailbox)nn### Important Note: ###nThis report is being generated automatically and does not constitute an investment recommendation. **Please consult a licensed investment advisor before making any investment decisions.**"
      },
      "typeVersion": 1
    },
    {
      "id": "28e1e96f-e27c-4933-afee-35931241060c",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        720,
        -100
      ],
      "webhookId": "79520027-d875-4ca3-a533-614bfca5e5b1",
      "parameters": {
        "options": {
          "appendAttribution": true,
          "respondWithOptions": {
            "values": {
              "formSubmittedText": "Success! Check your inbox (or spam folder) for your analysis report."
            }
          }
        },
        "formTitle": "Advance Stock Analysis",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Ticker symbol:",
              "placeholder": "TSLA",
              "requiredField": true
            },
            {
              "fieldType": "email",
              "fieldLabel": "Email:",
              "placeholder": "youremail@gmail.com",
              "requiredField": true
            }
          ]
        },
        "responseMode": "lastNode",
        "formDescription": "Please enter the companyu2019s NASDAQ ticker symbol (e.g. AAPL) to get a weekly email with combined technical-and-news sentiment analysis from our AI agent"
      },
      "typeVersion": 2.2
    },
    {
      "id": "4d9939ec-4a8e-40cb-95d2-24bbdbc27c8e",
      "name": "Refine Text",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1520,
        -100
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "="technicalAnalysis": {{ $json.output.technicalAnalysis }}"
            },
            {
              "content": "="recommendationText":  {{ $json.output.recommendationText }}"
            },
            {
              "role": "system",
              "content": "Ensure that the text in the "recommendationText" "technicalAnalysis" values is written in proper Hebrew, like a professional analyst.nReturn the same JSON format, but rewrite "recommendationText" "technicalAnalysis" values better.nu05e9u05d9u05dd u05dcu05d1 u05e9u05dbu05d5u05eau05d1u05d9u05dd "u05e8u05e6u05d5u05e2u05d5u05ea u05d1u05d5u05dcu05d9u05e0u05d2u05e8" u05d5u05dcu05d0 "u05d7u05d2u05d5u05e8u05d5u05ea u05d1u05d5u05dcu05d9u05e0u05d2u05e8""
            }
          ]
        },
        "jsonOutput": true
      },
      "credentials": {
        "openAiApi": {
          "id": "2m1HH5crgPAhTJlv",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    }
  ],
  "pinData": {},
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Organizing Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Think": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "GPT 4o": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Merge-2": {
      "main": [
        [
          {
            "node": "Warp as JSON for GPT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Refine Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get MACD": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "ChatGPT 4o": {
      "main": [
        [
          {
            "node": "Set Final Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Refine Text": {
      "main": [
        [
          {
            "node": "Generate HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Variable": {
      "main": [
        [
          {
            "node": "Merge-2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate HTML": {
      "main": [
        [
          {
            "node": "Adjust HTML Colors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Chart URL": {
      "main": [
        [
          {
            "node": "Download Chart",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get News Data": {
      "main": [
        [
          {
            "node": "Analyse API Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Variables": {
      "main": [
        [
          {
            "node": "Get News Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Chart": {
      "main": [
        [
          {
            "node": "First Technical Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Organizing Data": {
      "main": [
        [
          {
            "node": "Merge-2",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get Price History": {
      "main": [
        [
          {
            "node": "Calculate Support Resistance",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger1": {
      "main": [
        [
          {
            "node": "Generate Variables For API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Adjust HTML Colors": {
      "main": [
        [
          {
            "node": "Send Stock Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Bollinger Bands": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Trends Analysis Tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Warp as JSON for GPT": {
      "main": [
        [
          {
            "node": "ChatGPT 4o",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Input Trigger": {
      "main": [
        [
          {
            "node": "Set Stock Symbol and API Key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Technical Analysis Tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "First Technical Analysis": {
      "main": [
        [
          {
            "node": "Set Variable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Generate Variables For API": {
      "main": [
        [
          {
            "node": "Set Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Support Resistance": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Stock Symbol and API Key": {
      "main": [
        [
          {
            "node": "Get Chart URL",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Price History",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Bollinger Bands",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get MACD",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}