diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/.env b/financial-analyst-deepseek/financial-analyst-langgraph/.env new file mode 100644 index 000000000..ef50f1ae0 --- /dev/null +++ b/financial-analyst-deepseek/financial-analyst-langgraph/.env @@ -0,0 +1,4 @@ +AZURE_OPENAI_API_KEY="2pq............." +AZURE_OPENAI_ENDPOINT="https:........." +AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o" +AZURE_OPENAI_API_VERSION="...." diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/README.md b/financial-analyst-deepseek/financial-analyst-langgraph/README.md new file mode 100644 index 000000000..33e401ab7 --- /dev/null +++ b/financial-analyst-deepseek/financial-analyst-langgraph/README.md @@ -0,0 +1,71 @@ +# MCP-powered Financial Analyst using Langgraph and Azure openai GPT4o + +This project implements a financial analysis agentic workflow that analyzes stock market data and provides insights. + +We use: +- Langgraph for multi-agent orchestration. +- Azure open ai model +- Cursor IDE as the MCP host. + +--- +## Setup and installations + +**Clone the repository and navigate into the project directory:** + +**Fill Your Environment Variables** + +A `.env` file is already included in the project. +Open the file and fill in your actual API keys: + +```env +.env + +``` +**Install Dependencies** + + Ensure you have Python 3.12 or later installed. +``` + pip install -r requirements.txt +``` + +--- + +## Run the project + +First, set up your MCP server as follows: +- Go to Cursor settings +- Select MCP +- Add new global MCP server. + +In the JSON file, add this: +```json +{ + "mcpServers": { + "financial-analyst": { + "command": "uv", + "args": [ + "--directory", + "absolute/path/to/project_root", + "run", + "server.py" + ] + } + } +} +``` + +You should now be able to see the MCP server listed in the MCP settings. + +In Cursor MCP settings make sure to toggle the button to connect the server to the host. Done! Your server is now up and running. + +You can now chat with Cursor and analyze stock market data. Simply provide the stock symbol and timeframe you want to analyze, and watch the magic unfold. + +**Example queries**: +- "Show me Tesla's stock performance over the last 3 months" +- "Compare Apple and Microsoft stocks for the past year" +- "Analyze the trading volume of Amazon stock for the last month" + +--- + + + diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/building-financial-analyst-langgraph.ipynb b/financial-analyst-deepseek/financial-analyst-langgraph/building-financial-analyst-langgraph.ipynb new file mode 100644 index 000000000..afca841c6 --- /dev/null +++ b/financial-analyst-deepseek/financial-analyst-langgraph/building-financial-analyst-langgraph.ipynb @@ -0,0 +1,274 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "775c6bd5", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.graph import StateGraph, END ,START\n", + "from pydantic import BaseModel, Field\n", + "from langchain_core.runnables import Runnable\n", + "from typing import TypedDict, Literal, Optional\n", + "from langchain_core.messages import AIMessage, HumanMessage\n", + "import ast\n", + "from langchain_openai import AzureChatOpenAI\n", + "import os\n", + "from IPython.display import Image, display\n", + "from typing import Dict\n", + "from dotenv import load_dotenv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8eaffc83", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da83ef71", + "metadata": {}, + "outputs": [], + "source": [ + "#from langchain_community.llms import Ollama\n", + "#llm = Ollama(model=\"deepseek-coder:6.7b\")\n", + "#base_url=\"http://localhost:11434\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c9caa26f", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "\n", + "load_dotenv()\n", + "\n", + "\n", + "llm = AzureChatOpenAI(\n", + " azure_endpoint=os.environ['AZURE_OPENAI_ENDPOINT'],\n", + " azure_deployment=os.environ['AZURE_OPENAI_DEPLOYMENT_NAME'],\n", + " openai_api_version=os.environ['AZURE_OPENAI_API_VERSION'],\n", + " openai_api_key=os.environ['AZURE_OPENAI_API_KEY'] \n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "40577a14", + "metadata": {}, + "outputs": [], + "source": [ + "from langgraph.errors import NodeInterrupt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7428e74", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "\n", + "\n", + "class QueryFields(BaseModel):\n", + " symbol: str = Field(..., description=\"Stock ticker symbol (e.g., TSLA, AAPL).\")\n", + " timeframe: str = Field(..., description=\"Time period (e.g., '1d', '1mo', '1y').\")\n", + " action: str = Field(..., description=\"Action to be performed (e.g., 'fetch', 'plot').\")\n", + "\n", + "class QueryAnalysisOutput(BaseModel):\n", + " result: QueryFields\n", + "class StockAnalysisState(TypedDict):\n", + " query: str\n", + " parsed_output: QueryAnalysisOutput\n", + " generated_code: Optional[str]\n", + " execution_result: Optional[str]\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "def query_parser_node(state: StockAnalysisState):\n", + " query = state[\"query\"]\n", + " prompt = \"\"\"You are a Stock Data Analyst. Extract stock details from this user query: {query}. \n", + " \n", + " \"\"\"\n", + " finalprompt=prompt.format(query=query)\n", + " llm_with_struc=llm.with_structured_output(QueryAnalysisOutput)\n", + " response = llm_with_struc.invoke(finalprompt)\n", + " \n", + " return {\"parsed_output\": response}\n", + "\n", + "def code_writer_node(state: StockAnalysisState):\n", + " parsed = state[\"parsed_output\"]\n", + " if isinstance(parsed, dict):\n", + " raise NodeInterrupt(\"recieved wrong type\")\n", + " fprompt = \"\"\"You are a Senior Python Developer. Generate code to {action} the stock data.\n", + " Stock: {symbol}\n", + " Timeframe: {timeframe}\n", + "\n", + " Use yfinance, pandas, and matplotlib libraries. Output should be a clean, executable .py Python script for stock visualization without explanations or AI-generated messages—just the direct script content.without ''' or any code blockers\n", + " \"\"\"\n", + " action=parsed.result.action\n", + " symbol=parsed.result.symbol\n", + " time=parsed.result.timeframe\n", + " ffprompt=fprompt.format(action=action,symbol=symbol,timeframe=time)\n", + " code = llm.invoke(ffprompt)\n", + " return {\"generated_code\": code}\n", + "\n", + "\n", + "def code_result(state: StockAnalysisState):\n", + " \n", + " ans=StockAnalysisState[\"generated_code\"]\n", + " return {\"execution_result\": ans}\n", + "\n", + "\n", + "graph = StateGraph(StockAnalysisState)\n", + "\n", + "graph.add_node(\"QueryParser\", query_parser_node)\n", + "graph.add_node(\"CodeWriter\", code_writer_node)\n", + "graph.add_node(\"CodeExecutor\", code_result)\n", + "\n", + "\n", + "graph.add_edge(START,\"QueryParser\")\n", + "graph.add_edge(\"QueryParser\", \"CodeWriter\")\n", + "graph.add_edge(\"CodeWriter\", \"CodeExecutor\")\n", + "graph.add_edge(\"CodeExecutor\", END)\n", + "\n", + "\n", + "workflow = graph.compile()\n", + "\n", + "\n", + "display(Image(workflow.get_graph(xray=1).draw_mermaid_png()))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "1c086ece", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'query': 'Plot YTD stock gain of Tesla', 'parsed_output': QueryAnalysisOutput(result=QueryFields(symbol='TSLA', timeframe='YTD', action='plot')), 'generated_code': AIMessage(content='import yfinance as yf\\nimport pandas as pd\\nimport matplotlib.pyplot as plt\\n\\n# Define stock and timeframe\\nstock = \"TSLA\"\\ntimeframe = \"ytd\"\\n\\n# Fetch stock data using yfinance\\ndata = yf.Ticker(stock).history(period=timeframe)\\n\\n# Plot stock data\\nplt.figure(figsize=(12, 6))\\nplt.plot(data.index, data[\\'Close\\'], label=f\"{stock} Close Price\", color=\\'blue\\')\\nplt.title(f\"{stock} Stock Price - Year to Date\", fontsize=16)\\nplt.xlabel(\"Date\", fontsize=14)\\nplt.ylabel(\"Close Price (USD)\", fontsize=14)\\nplt.legend(loc=\"upper left\")\\nplt.grid(alpha=0.3)\\nplt.tight_layout()\\n\\n# Show the plot\\nplt.show()', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 157, 'prompt_tokens': 81, 'total_tokens': 238, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-11-20', 'system_fingerprint': 'fp_ee1d74bde0', 'id': 'chatcmpl-BcBoSbPYUDT6bVDiZKQnIsMloX4LG', 'service_tier': None, 'prompt_filter_results': [{'prompt_index': 0, 'content_filter_results': {'hate': {'filtered': False, 'severity': 'safe'}, 'jailbreak': {'filtered': False, 'detected': False}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}}], 'finish_reason': 'stop', 'logprobs': None, 'content_filter_results': {'hate': {'filtered': False, 'severity': 'safe'}, 'protected_material_code': {'filtered': False, 'detected': False}, 'protected_material_text': {'filtered': False, 'detected': False}, 'self_harm': {'filtered': False, 'severity': 'safe'}, 'sexual': {'filtered': False, 'severity': 'safe'}, 'violence': {'filtered': False, 'severity': 'safe'}}}, id='run--d4b817db-a0e0-433e-82ee-9740f1f18a89-0', usage_metadata={'input_tokens': 81, 'output_tokens': 157, 'total_tokens': 238, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}), 'execution_result': __main__.StockAnalysisState['generated_code']}\n" + ] + } + ], + "source": [ + "inputs = {\"query\": \"Plot YTD stock gain of Tesla\"}\n", + "\n", + "\n", + "result=workflow.invoke(inputs)\n", + "print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "4c0fb0ea", + "metadata": {}, + "outputs": [], + "source": [ + "p=result[\"generated_code\"].content" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "aaadedba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'import yfinance as yf\\nimport pandas as pd\\nimport matplotlib.pyplot as plt\\n\\n# Define stock and timeframe\\nstock = \"TSLA\"\\ntimeframe = \"ytd\"\\n\\n# Fetch stock data using yfinance\\ndata = yf.Ticker(stock).history(period=timeframe)\\n\\n# Plot stock data\\nplt.figure(figsize=(12, 6))\\nplt.plot(data.index, data[\\'Close\\'], label=f\"{stock} Close Price\", color=\\'blue\\')\\nplt.title(f\"{stock} Stock Price - Year to Date\", fontsize=16)\\nplt.xlabel(\"Date\", fontsize=14)\\nplt.ylabel(\"Close Price (USD)\", fontsize=14)\\nplt.legend(loc=\"upper left\")\\nplt.grid(alpha=0.3)\\nplt.tight_layout()\\n\\n# Show the plot\\nplt.show()'" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "ad9ba854", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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jDPOCPXs2TN04IEHZvo97777burj2KRJE+/x6datW+rz47zzzgsVtEsuucS7744dO4Z27doV6tq1q/f1pZdeus/1rr/+eu/8QoUKhdq0aRM67bTTQm3btvV+t4ULFw69+uqr+922PZ52/aZNm4Z69erlfc+RRx6Z+pg9/vjj+32PPaftst69e4caNGgQqlixovf7se8966yzcnxt2PPZfzztOZj+ef7LL7+kXvfFF1/01mbXa9Gihfd779ChQ+rahg4dGtbj6K8743M6M0888YR33TJlyniPue/vv//2zi9fvnyoXbt23s9sj1utWrW886tWrRpauHBhnl7Xy5Yt834Pdj17fR9zzDHe88/Wa+cdcMABocWLF4f1MwMAkg9BFAAAYQZRFrIUKVLEu17JkiVDp556qvdmeMKECaEtW7ZEJYiyN7x+UOGzEMzevNsb4XDf/FmoYm+c/fW0bt06dOutt3pvOu2NbHbszWl2Adb27dtT35haELFz587Uy/744w/vzapd9t///nef75sxY0aoaNGiXijx5JNPemtMz35Gu052QdS8efNS7/u2224LhSu738/o0aNTL//mm2/2WYMd6tSpE1qwYEGmt5tVEGU/p51fuXLl1NtMb+rUqaElS5akfv3zzz97YZgFUe+///5+j48fEgwfPjxUkDZt2pQanPlBjAUbmzdv3u85fNBBB4Vmz569z/d/9913obJly3pB3m+//bbPZWPGjAktX758v/ucNGlSqFy5ct5zJmMg7Ac6drAga8OGDWH/TP7zyH7HmbHfhf07YM/X119/fb81289i3z927NioBFHff/996s/4+++/7xNaf/zxx/sFsPY6vOWWW7zrWzAV7ut67969Xkhl17Ew3u7HZ0GYHzJaCAkAQHYIogAACDOIMp9++qkXPPjX9w/2ptgqlLJ685nXIMqqRuz7nnrqqX3OtzeUdn76SqHcsjf3VnmT8WewQ6NGjUL3339/aOvWrWG/YX3jjTe8y60Cw0KpjN577z3vcgsetm3blnr+SSed5J1vFUK5kTGI+vrrr0MVKlTwfgeZVdbkRma/H6sYefvtt0PVqlVLDQP9kCx9EJUxjMgpiLI371adYudnDJWyYpVldv2HH344y5DULm/ZsmWooFklkV8dZMcWlPjs8fIrctKHiek9+OCD3uUWaOSWH6w888wzmQY6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5cuHunbtGjrzzDNDJ554YqhJkyapl9nPtGXLln2+d/bs2d7273awy8877zxvK/uPP/449TrTpk0LVapUKXUr+v79+4d69eoVKlGihHdejx49Qjt27NhvXcOHDw8VLVo09ftOPfXU0CmnnOJtGZ+SkhK64447Uq+7aNGiLLe6v+WWW7zLqlevHvr5559DueX/3PZcyI3s1pBely5dMr3dvXv3hi699NLU+23RokXojDPO8B4re25l9j3vvvtuqFSpUt5lderUCR133HGhs846K9SzZ0/vazvfHu8gnHPOOd7923FmBg8enPqzHnbYYd5ryX7eo48+OlShQgXv/Oeeey71+uvWrfMeWzu/cuXKoZNOOinUr1+/ULVq1UJly5YNXX311Zne37Bhw7JdR248/fTT3m2UKVPGew7ac9wOv/76a+p1XnjhBe91YNc78sgjvX8HjjrqKO+5aufZazgc/rpLly7trd0OZ599tvdzN23aNPW+bE1PPfWU9/zJ6P3330+9f/see3y7devmva7suEOHDpk+r3Lzul62bJn3WvTXaLdlt++/Ru3fPbts27ZteXrMAQDJgSAKAIAwg6ilS5d6bxgHDhwYatasmfemuEiRIt4b4yOOOCJ0xRVXhObOnZvp9/q3n9Phzz//TH0Dbm+Ic8PerNr1L7vsshyva28Uv/zyy9CNN97ovXG2+7KQyA716tXzbuudd97J9I2uH2TZ99nP7L/pTR8SmSVLloQuv/xyL1CxkMyu2759ey9o2LVrV5ZrmzdvnvcGuEGDBqHixYt7Qdmhhx7qPa52WW5DoPvuu8+73MLBqVOnhmIxiPJ9/vnnXihjwZkFBlWrVg21adMmdOedd4b+/fffTO/32muvDR1++OFeIGC/N1uDBTr3339/6Pfffw/FYhBlfvjhBy84s/Xa79eeF40aNfKecy+//HJo7dq1+1x/9erVof/85z+hhg0betevVauW99pbuHBhloFTJIKoPXv2eM8hC8z8ADWz3+GUKVO8wLRGjRrevwMWmPXu3Ts0duzYsO/TX3f6gz0fLNS18NpCHwu/NmzYkO3tTJgwIdS9e/dQlSpVvNDSnif33HOPF/5m91zMzet6+/btoeeff94Lr+1ntZ/Z/g20IMpe7/bvCgAA2Umx/1AcBgAAAAAAgGhjRhQAAAAAAAAKBEEUAAAAAAAACgRBFAAAAAAAAAoEQRQAAAAAAAAKBEEUAAAAAAAACgRBFAAAAAAAAApEkYK5m/izd+9eLV++XGXLllVKSkrQywEAAAAAAAhUKBTSpk2bVKtWLRUqlLfaJoKoLFgIVbdu3aCXAQAAAAAAEFP+/vtv1alTJ0/fSxCVBauE8h/ccuXKKdart1avXq2qVavmOZEE4PB6QjLj+Q9EDq8nIDy8ZoD4eE1t3LjRK9rxM5O8IIjKgt+OZyFUPARR27dv99bJP9pA/vB6QjLj+Q9EDq8nIDy8ZoD4ek3lZ4QRr3AAAAAAAAAUCIIoAAAAAAAAFAiCKAAAAAAAABQIZkTlw549e7Rr166Y6P20dVj/J/3Uyado0aIqXLhw0MsAAAAAACBHBFF5EAqFtHLlSq1fv16xsh4LozZt2pSvgWGIXxUqVFCNGjX4/QMAAAAAYhpBVB74IVS1atVUqlSpwN/8WxC1e/duFSlSJPC1oOB/91u3btWqVau8r2vWrBn0kgAAAAAAyBJBVB7a8fwQqnLlyooFBFHJrWTJkt6xhVH2vKRNDwAAAAAQqxgoFCZ/JpRVQgGxwn8+xsLMMgAAAAAAskIQlUdUHiGW8HwEAAAAAMQDgigAAAAAAAAUCIIoxJWjjz5a11xzjeLN0KFD1bx586CXAQAAAABAoAiikqh1K7uDBSXmww8/VLt27VS+fHmVLVtWhx122D7Bz2uvvaYKFSrk6j6bNGmi4sWLe7sM5sbOnTv14IMPqlmzZt7MoypVquioo47SsGHDYmb20bfffrvP41a9enX169dPf/75Z7bfd8MNN+jrr78usHUCAAAAABCL2DUvSaxYsSL19DvvvKMhQ4ZowYIFqeeVKVPGC0r69++ve+65RyeeeKIXtMyfP1/jxo0L+/6+//57bdu2TaeeeqqGDx+um266KccQqkePHpo9e7buvvtuL4AqV66cpkyZoocfflgtWrSIqYoie+wsqFu4cKEuvvhinXDCCfr555/327HOdjS0nRbt8bUDAAAAAADJjIqoJFGjRo3Ug1U7WciU/jwLST799FMvABo8eLAaN26sRo0a6aSTTtIzzzwT9v298sorGjBggM4++2y9+uqrOV7/8ccf14QJE7ww7PLLL/dCpwMPPNC7jalTp+rggw/O9PvWrVunQYMGqWLFil4VVc+ePb1wyPfXX395IZFdXrp0aa/Ca8yYMamXz5071/se+/mtusnWu2bNmhzXW61aNdWsWVOdO3f2Qj0L7H7//ffUiqnPP/9cLVu29CrCLJTLrDXPHhdbj13HbuuKK65IvWz9+vW68MILVbVqVS+Q69atmxfSAQAAAAAQzwiiIiAUkrZsCeZg9x0pFkjNmzfPC2fyY9OmTRo1apQGDhyoY489Vhs2bNDEiROz/Z633npLxxxzjFf5lFHRokW9ECkz5557rmbMmKFPPvlEkydP9iqQevXqldrKZ6HWjh07vJBrzpw5euCBB1IrkyzssYDH7tNu44svvtA///yj008/Payft2TJkqlVXb6bb75Z999/v3755RcdccQR+33Pc889563NqqlsXbb+gw46KPXy0047TatWrfICrZkzZ+rII49U9+7dtXbt2rDWBgAAAABALKE1LwK2brXWtmDue/NmqVSpyNzWlVde6QVGTZs2Vf369b1ZUccdd5zOOussr2ont0aOHOlVMFm1jznjjDO8CqlOnTpl+T1WxWSDyMNh32MBzg8//KAOHTqkBlp169bVRx995IU5S5Ys8WY42c9krMrK9/TTT3sh1L333rtPlZJ9/2+//eZVhOWm5dFaB2vXru1VkU2aNMk7/6677vJCuKz873//0/XXX6+rr7469bzWrVt7x1ZBNW3aNC+I8h93uw/7md577z0vvAIAAAAAIB5REYVUVnX02WefeS1mt912m1c5ZGFJmzZttNXStlyyMMeqoXx22iqkrFIqK1bJFC6rNipSpIjatm2bel7lypW9QMguM1dddZUX+ljL4R133OHNcfJZq9v48eNT5zfZwQasmz/++CPb+65Tp473eNWqVUtbtmzR+++/r2LFiqVe3qpVqyy/1wKm5cuXexVOmbF1bd682ftZ0q9t0aJFOa4LAAAAAIBYRkVUBFhFklUmBXXfkdawYUPvYDOKbr31Vq8yyAacn3feeTl+r81KsgHjVtGTfkC5Dey2SqmLLroo0++z+/j1118VafYz2BB0C9jGjh2r++67T4888ohX/WVhj82Psna9jGxmU3ascsxmN9msKBtanlFWrYTpW/myYuuy+7d5UxnldsdCAAAAAABiEUFUBKSkWPAQ3P1Hck5URgcccIA3BNyqfnLDWvBsgHfGAefDhg3zLssqiLKh5P/973/1008/7TcnyuY92fyljOHOIYccot27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AAAAACSTmA2ipk+frhdeeEFH+D1e/+/aa6/Vp59+qlGjRum7777T8uXLdcopp6RevmfPHi+E2rlzpyZNmqThw4frtdde05AhQwL4KWIPQZS0YIF01FGuQsYeB5tnZF+XKCFdeaW7ziOPuPlBGR83qySL1mytRAyjrDKqTBlp/Phgwqi//5YuuMCdHjzYVcCld+aZ7ndqv9+RIwt2bQAAAACQjGIyiNq8ebPOOussvfTSS6pYsWLq+Rs2bNArr7yiRx99VN26dVPLli01bNgwL3CaMmWKd52xY8dq/vz5evPNN9W8eXP17NlTd999t5555hkvnEp2BdWa17SpC2zs/jIUrAVq+nSpY0ermpMaNZImTZIOPzzt8ssuc216P/4offdd2vnMh8qb9u3TwqhvvpFOPLHgwijbsfHss11Lpe3q97//7X+dYsWyDh8BAAAAAEkSRFnrnVU1HXPMMfucP3PmTO3atWuf85s0aaJ69eppsvVYyVqtJqtp06aqXr166nV69OihjRs3at68eUp2BVURVbq02z0vlgaWW/td167SmjUumPj+e6l+/X2vU7my2z3PDyZ8BFF516GD9MUX7jnx9dduOPy2bdG/30cfdWGihWAjRrjQKTOXXCKVKiX9/LMLywAAAAAA0VNEMWbkyJH68ccfvda8jFauXKlixYqpQoYhPRY62WX+ddKHUP7l/mVZ2bFjh3fwWXBl9u7d6x1ima0vFArlap3Ll1tfWYpq1LCfK7rratYsRb/9lqKfftqrDJligXvnHRtGnqJdu1LUvXtI778f8uYXZfYYXH21zRRK0ejRKZo3b68OOST942aPM2UzeamMGjNG6tUrRV99laITTwzpo49CXvVZtLz4ovudPfTQXh14YOa/a2P/nJx7boqefTZFDz8cUpcuuX89AYkmnP+fAMgerycgPLxmgPh4TUXi9mIqiPr777919dVXa9y4cSphA3sK0H333ac777xzv/NXr17tDUiPZfZEsLZFe5IVKpR1kdvmzSnavNmFckWKrNaqVdENVA46qLSkspo6dYdWrdqgoAwbVkq33lpWoZAFINv05JMbvIqcrKpyypeXjjuugr78soTuu2+7Hn54oxYtKieplMqW3axVqwLeAi5OWSvkm28W1VlnVdRXXxVS7947NWzYuqiEUYsXF9bvv1dVkSIhde+e83N94MDC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6t5771XhwoV19tln67LLLlOVKlX07LPP6iPrAwnDc889pyOOOELlypXzDu3bt9fnn3+eevnRRx/t7cSX/nBpho/zlyxZot69e6tUqVKqVq2aBg8erN32MT0AwHPbbdI550h79kinn+52h4tkW54FOfFcRWRl102butM//RT0agAAAFDQbES2bY5z7LFSt25BryaxhPU2YfLkyerQoYMXEKX3wgsveIHQ888/r9dee01PP/20fvjhBxUtWtT7Ohx16tTR/fffr5kzZ2rGjBnq1q2b+vbtq3np9ua+6KKLtGLFitTDgw8+mHrZnj17vBBq586dmjRpkoYPH+6tYciQIWGtAwASmX2i8+KLUteu0qZNbpi3DfeOl0HlBYE5UQAAAMlpzhzpzTfdaX/HPAQURC1fvlzNmjXb73yriLJw6txzz00976CDDlKvXr28MCkcJ5xwgvd9Bx98sBo1aqR77rlHZcqU2acd0CqdatSokXpIH4yNHTtW8+fP15tvvqnmzZurZ8+euvvuu/XMM8944RQAwLEB3u+/73YAWbpUuvHG/N8mQRQAAADi3a23SqGQdNppUqtWQa8myYeVr1u3TiVLltyvDW716tVeFVKhDH0YFkaNsf3C88iqm6wVcMuWLV6Lnu+tt97ygiYLoSy4uv32271wyq/aatq0qapXr556/R49enjtglZV1aJFi0zva8eOHd7Bt3HjRu9479693iGW2fpCoVDMrxOIB8n2eipf3m1J27t3If30k/3coXzd3i+/WPN8ipo0sX87FdeOOML+W0izZuX/cYkXyfb8B6KJ1xMQHl4zseuzz9yogmuukcqUUcL74Qfp008LqXDhkO68056Tikt7o/SaisTthRVElS1bVsuWLdvnvOnTp3vHNqg8I2vXK2HTXsM0Z84cL3javn27Vw314Ycfps6lGjBggOrXr69atWrp559/1k033aQFCxboA9uLXNLKlSv3CaGM/7VdlpX77rtPd955537nW8hm64hl9kTYsGGD9yTLGAYCCE8yvp6qVCksqar++MP+nVyV59lO9qnR/PnVvCCqWrV/tWrVHsWzmjVtDmE1LV+eovnzV6tKlTj9KyQMyfj8B6KF1xMQHl4zsWnt2hSdfno1bd+eonff3aXhw9epdu3E/ZvI/p4dPLiS9Q6of/9tqlhxo1atUlzaG6XX1Cab61GQQZQNER89erRXoVS6dGnvPAuJLHDq3Lnzftf/448/vMAoXI0bN9asWbO8B+29997TOeeco++++84Loy6++OLU61nlU82aNdW9e3fvvhraPuR5dMstt+i6667bpyKqbt26qlq16n4zsWLxCWa/A1sr/2gD+ZOMr6dKlaSiRUPasSNFu3ZVU926ebudv/+27W0LqUiRkNq2rayiRRX3Dj5Y+u03a12sogz7dCSkZHz+A9HC6wkID6+Z2DRsmLwQysybV1R9+lTVRx+F1Lq1EpLtkzZ1aiEVLx7SffeVULVq4RfWJPprqkQeio3yFUSdf/75GjRokLp06eId//bbbxoxYoTq1avn7WaXsa1uwoQJ6mqTcMNUrFgxr63Pr7SyqqsnnnjCG4qeUdu2bb3j33//3QuirF1v2rRp+1znn3/+8Y7tsqwUL17cO2Rkv7B4+IfQnmDxslYg1iXb68lmRTVo4AKXP/8spPr183Y7Cxa444MOSlHx4omxv63NibLH5eefC+n445UUku35D0QTrycgPLxmYovtGPfMM+703XdL77wjzZ2boqOPTtHw4W7n5URiHWc2G8pceWWK6tWL/79nU6LwmorEbYV1CwMHDvSqk3788Udde+21evbZZ712vVdeeWW/xXz22Wdas2aNN58pEkle+vlN6VnllLHKKGMtfdbatypd/dy4ceO8qia/vQ8AsK//z/71++95v41EGlTuY2A5AABIVrapjU3msUk3gwdLkya5nZZtck3//i6csla2RGFB2+zZkjVE3Xxz0KtJbGFVRJlhw4bpggsu8IaCV65c2Quaateuvd/1rLroscceU9++fcNukbOd7qzKynoP3377bX377bf68ssvvfY7+9p21bP7thlRFohZW6C1DZrjjjvOC5zOPvtsPfjgg95cqNtuu02XX355phVPAIDIBlGJlPkTRAEAgESxeLH04otW7WOFHDlf//HH3fF//mPv793h44/dTsuPPioNGSL9+qv0yivWrqW4tnOndNtt7rT9fJUrB72ixBZ2EGU6duzoHbJjAVVeqqGsksna/lasWKHy5ct7AZOFUMcee6z+/vtvffXVV3r88ce9OVU2w6lfv35e0OQrXLiwN8fKdsmz6iibZWVVXHfddVdeflQASApURGXO32jV2g63bpX+f4NWAACAuDN0qLyWusmTpW++sbatrK87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tMfGdnoBAACIh2oo+zvNAph4ctxxUoUKbpOYiROzv+4997jjDh3cBjPr10s33ujmT73+uguo7rjDXcdmRJUvH/31I0JB1MEHH6zLL79cixYtUjh27dqlESNG6LDDDtMrr7wS1vcCAAqWP7TRdjGxQ06SYVC5r1o1V/VlMwjmzAl6NQAAAJGZDxWLihWTTj7Znbb2vKxYxZd/+TPPuMp1G21dp470999ulz4bX211NbVruxY+xFEQ9cADD+idd97RQQcdpC5duuipp57S9OnTvaApo6VLl+r999/XpZdeqpo1a2rgwIGqX7++BgwYEOn1AwAiqHTptBY7f/ZTdpJlUHn6OVGGOVEAACBeKqKsUige+e15778v7d6d+XXuu0/au1fq08f9nVa4sHTuuS6geuABV/20apW77tChBTOQHREcVn7NNdfo3HPP1aOPPupVNl199dVKSUnxdsqrUKGCd9i+fbvWrl3rHRu7vEePHrr++uvVrVu33N4VACDg9rzly10Lmm31m51kDKLGjGFOFAAAiG07dkgzZsRvRZSxCKFyZTfravx46dhj973cmrVs9pPJuAueBU7WnnfhhdKjj7rHwwIqxOGueRY23XXXXbrjjjv0+eef6+uvv9akSZO8Cqi///5bJUuWVO3atdW0aVOvaqpv375eJRQAIL6CqAkTcp4TZYMjFyxIviDKEEQBAIBYNnOmC1+qVk2bARpvihaV+vWTXnzRtd9lDKKs4sn+HrXz27bN/DZsNtb//lcgy0W0gihf4cKF1adPH+8AAEjOgeV//eV2Iyle3PXeJwN/5zybEWXVYMkSwAEAgPidDxXPG8pYe54FUR98ID37rJsdZZYudbOgzO23B7pERHNGFAAgOeQ2iPIHlTdu7Prxk2WY+2GHuU8YrW3x3XeDXhEAAEBiDSpPr0sXqXp1ad066auv0s5/8EFp5053eadOQa4QeUEQBQDIUxCVbPOhTKFC0jffSF27Slu2uE/prrnGdogNemUAAACO7fDrDyqP9yDKPuw89VR32t8db+VK6aWXMp8NhfhAEAUA2EfDhu7YdhjZuDHr61l7WrIFUaZaNWnsWOnmm93XTzzhgikb8A4AABA0+zDRBnzb+IQjj1Tc83fP++gjNxbikUfccbt2UvfuQa8OeUEQBQDYR7lyLmwxf/yR+XW2bpU+/tidTsZy6CJF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ct75ffv2VbFixSK3UgAAkghBFAAAiW3PHunBB93p666TePuMZFEk3zdQpIhOPvlk7wAAACIbRNmnpLt32/9vg14RAACIpI8+kmz/rwoVpIsuCno1QMGJeAfqxo0bNW7cOG9YubXoAQCA8FWv7sIn+7R05cqgVwMAACLJ3io/8IA7ffnlUtmyQa8IiIMg6qWXXlKXLl20bt261PNmz56tJk2aeIPKjz76aHXq1Elbt26N1FoBAEgahQu7eRGG9jwAABLL+PHS9OlSiRLSVVcFvRogToKoN954Qzt27FDFihVTz7v++uu1atUqnXfeeerVq5cmT56s5557LlJrBQAgqdSp444JogAASCx+NdT550vVqgW9GiBOgqjffvtNzZo1S/3633//1fjx43XhhRfq5Zdf9gaYt27dWm+99Vak1goAQFLOiVq0KOiVAACASPnpJ2nsWKlQISvmCHo1QBwFUevXr1fVqlVTv7aZUOaUU05JPa9jx45avHhxftcIAEBSOvJId/z990GvBAAARLoa6vTTpQMPDHo1QBwFUZUrV9YK28rn/3399dcqXLiwjjrqqNTzbFj5rl27wrpda+U74ogjVK5cOe/Qvn17ff7556mXb9++XZdffrl3/2XKlFG/fv30zz//7HMbS5YsUe/evVWqVClVq1ZNgwcP1m7bcggAgDjSvbs7/u47t3MeAACIb3/8IY0a5U7fdFPQqwHiLIiysOjjjz/W3Llz9fvvv+vtt9/2QqjSpUunXseqoWrWrBnW7dapU0f333+/Zs6cqRkzZqhbt27q27ev5s2b511+7bXXem1/o0aN0nfffafly5fvU4W1Z88eL4TauXOnJk2apOHDh+u1117TkCFD8vqjAgAQCOuAt1GMmzZJM2YEvRoAAJBfjzwi7d0r9eghNW8e9GqAOAuibrzxRm/HPJsT1bhxY69V77rrrku9fO/evfr+++/VsmXLsG73hBNO8AadH3zwwWrUqJHuuecer/JpypQp2rBhg1555RU9+uijXkBltz1s2DAvcLLLzdixYzV//ny9+eabat68uXr27Km7775bzzzzjBdOAQAQTzvnde3qTn/9ddCrAQAA+WGNPK++6k5TDYVklucgqmvXrvrkk0908skne4d33nnHC5F8P/zwg2rVqrVPtVK4rLpp5MiR2rJli9eiZ1VS1up3zDHHpF6nSZMmqlevnrdDn7Hjpk2bqnr16qnX6dGjhzZu3JhaVQUAQLy15xFEAQAQ3558UtqxQ2rTRjr66KBXAwSnSH6+2Vrg7JCZTp066SfbDiAP5syZ4wVPNg/KqqE+/PBDHXrooZo1a5aKFSumChUq7HN9C51Wrlzpnbbj9CGUf7l/WVZ27NjhHXwWXPmVXXaIZbY+m8cV6+sE4gGvJ8Qa94dqIU2aFNKWLSGVLBm9++L5D0QOrycgPIn+mrG3l88+myIpRYMH289qM5WDXhUS2d4ovaYicXv5CqKixVr9LHSyVrz33ntP55xzjjcPKpruu+8+3Xnnnfudv3r1ai8Qi2X2RLDHyp5khWwPUAB5xusJscZmRNWoUVUrVxbWmDHr1KlT9NrMef4DkcPrCQhPor9mnnuulNavL6eGDXerffs1WrUq6BUh0e2N0mtqkw0vDTqIeuutt7xh4BYcWRWR7XTXokULnXvuuRowYECebtOqng466CDvtM2Bmj59up544gn179/fm/Nk86jSV0XZrnk1atTwTtvxtGnT9rk9f1c9/zqZueWWW/aZcWU/S926dVW1alXvZ4r1J1hKSoq31kT8RxsoSLyeEIuOOSZFb74p/fhjRfXrF72PT3n+A5HD6wkITyK/Zqzx5uWXU/5/NlQh1axZLeglIQnsjdJrqkSJEsEFUTa/6fTTT9dHH33kJWy2GJsJZaHPV199pa+//lrvv/++t7tdfn9oewCtbc5CqaJFi3q33a9fP++yBQsWaMmSJV4rn7FjG3C+atUqVavmXuDjxo3zwiRr78tK8eLFvUNGtvZ4+IfQnmDxslYg1vF6QizOibIgavx4e266P2Sjhec/EDm8noDwJOprZsQIaflyqVYtadAg+/mCXhGSRUoUXlORuK0838KTTz7pzW466qijvMHkW7du1aJFi7xj28WuY8eOXkj11FNPhXW7Vpk0YcIELV682JsVZV9/++23Ouuss1S+fHldcMEFXuXS+PHjveHl5513nhc+tWvXzvv+4447zguczj77bM2ePVtffvmlbrvtNl1++eWZBk0AAMTLwPLp06UNG4JeDQAACMczz7jja66xAoigVwMEL89B1PDhw9WoUSOvOsmvRvJZKGRVUXb5sGHDwrpdq2QaNGiQNyeqe/fuXluehUnHHnusd/ljjz2mPn36eBVRnTt39trtPvjgg9TvL1y4sEaPHu0d27oGDhzo3d5dd92V1x8VAIBA1a0rHXywVQhLUR6ZCAAAImj9esnfw2vgwKBXA8SGPLfm/fbbb7riiiu8VrnM2PknnHCCnn766bBu95VXXsn2cmsBfOaZZ7xDVurXr68xY8aEdb8AAMSybt2khQulb76RTjwx6NUAAIDcmDLF7Y7XsKFUs2bQqwHivCLKBopv2bIl2+vY5XY9AAAQmfa8r78OeiUAACC3vv/eHR91VNArARIgiLKd8d59910tt6lrmVixYoV3+ZFHHpmf9QEAAEldu7rjuXNtN9igVwMAAMIJojp2DHolQAIEUTYw/N9//1WrVq30yCOPaMaMGfr777+944cfftjb4W7t2rXe9QAAQP5UqSI1a+ZOW3seAACIbTt3StOmudNURAERmBFl858scLr55pt144037nNZKBRSkSJFvMttsDgAAIhMe97s2S6IOvPMoFcDAACyY0PKt22TKlWSmjQJejVAAgRRxqqdTjrpJL311luaNWuWNm7cqHLlynltewMGDNCBBx4YuZUCAJDkLIh69FHmRAEAEA9++MEdd+ggFcpzLxKQePIVRBkLm26//fbIrAYAAGSpUyepSBFp0SJ3aNAg6BUBAICsMB8KyBy5LAAAcaJsWalNG3eaOVEAAMSuUCitIoogCshjRdSECROUV507d87z9wIAgH3b8yZNcu15F1wQ9GoAAEBmfv9dWrVKKlZMatky6NUAcRpEHX300UpJScnTnezZsydP3wcAAPbVrZt0992uIso+bQ3nf812/VtukXbvlu65RypePJorBQAgefnVUK1bSyVKBL0aIE6DqCFDhuQ5iAIAAJHRvr1UsqT0zz/S/PnSYYfl/nvnzZMeeMCd/vFH6cMPpfLlo7ZUAACU7POhjjoq6JUAcRxEDR06NLorAQAAObIqJps1MW6ca88LJ4j64ou00+PHu+Hnn38u1a4dlaUCAJLQpk3SHXdIJ51kI1qUtBhUDmSNYeUAAMThnChjQVQ4LHQyF14o1aghzZnjKqysUgoAgEj43/+kxx6TLr5YSWv1amnBAne6Q4egVwMkQBB1zz336L///a927dqV5XV27tzpXef+++/P7/oAAEAmc6LMt9+6eU+5sXmzNHGiO33DDdLkyVKTJtLff7tPa7/7LnrrBQAkB2sbf/ppd9qCmF9+UVKy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EuyhtVDqvvtSdPvtihs2G8raC22AduvWhRKizSnWX09W0G9/nu7YkaIVK1LUoIEC3TWvYsXYfH3lNCfKgqiJEwvpggsU1yZOdMctW6aobNn4+j0k+v+DgGR6TRWKwG3F3CvcysYshPrwww/1zTffqEEu/o87a9Ys79gqo0z79u01Z84crVq1KvU648aN8yqbDrXJfgAAICEHlltV1OYC6Bizz7sWLsz99d991x336iU995w7fccd0uefK274+8mceKLbHQ3RZ4+z/3ns0qXBrSNeh5X7QZSxnfPinQ1dN126BL0SAEiwIMra8WwI+dtvv62yZct6M53ssM3qwSWv/c52wLNd9BYvXqxPPvlEgwYN8nbUO+L/65ePO+44L3A6++yzNXv2bH355Ze67bbbvNvOrOoJAADEN3uzbkPK9+xxIVE0WSBgFVhHHSVt3Zq7tiY/iDr9dOncc6VLLnHn2/brixYpLvhv5Lt3D3olycUq0ILeOc8PosqXV1yG1IULu7a2xYsV1wiiACSKmAuinnvuOW+g1tFHH+1VOPmHd955x7u8WLFi+uqrr7ywqUmTJrr++uvVr18/fWrbuPy/woULe219dmzVUQMHDvTCqrvuuivAnwwAABREVZRt1x5N06fbznE2t0caMSLn61uVllVP2UiFPn3ceU88IbVpI61bJ51yipu/FMtswsH8+a5ChzfBBcuviIqFICoeK6LKlHFzouK9KmrZMvtA3rX2WggOAPGsSCy25mXHBoh/538ckA3bVW/MmDERXBkAAIhl9uZs5Ejphx+iP+/J9/TT0vnnZ9+qlr4tr2xZd9oKtN97z2a92IgB6bLLpGHDYrflzf/Ty4rPK1UKejXJJZYqouIxiPLb86ZMcc9jq0iMRxMmuOPmzeOzMg0AYroiCgAAID8VUTaYeO/eggmiLETKrgIrY1texoDBgjOrcBg+XHrhBcUsv5LEn7eDgg+igpwR5Q8rj9cgyq/ii+eKKNryACQSgigAAJAQrFrHtjO3N83WRhYtc+a440aN0qqisvLTT66dpmRJqXfv/S/v1k26/353+qqrXNVGLBo/3h137Rr0SpIPFVGRqZa0OVE2Iype50T5FVGdOwe9EgDIP4IoAACQEIoUkdq2je6cqC1bpN9/d6efesodW4vdihWZX9+vhrIQymbVZOaGG6R+/dzcqVNPldJt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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "exec(p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31647732", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/finance_langgraph.py b/financial-analyst-deepseek/financial-analyst-langgraph/finance_langgraph.py new file mode 100644 index 000000000..329be362a --- /dev/null +++ b/financial-analyst-deepseek/financial-analyst-langgraph/finance_langgraph.py @@ -0,0 +1,109 @@ +from langgraph.graph import StateGraph, END ,START +from pydantic import BaseModel, Field +from langchain_core.runnables import Runnable +from typing import TypedDict, Literal, Optional +from langchain_core.messages import AIMessage, HumanMessage +import ast +from IPython.display import Image, display +from typing import Dict +from langchain_openai import AzureChatOpenAI +import os +from dotenv import load_dotenv +from langgraph.errors import NodeInterrupt +import yfinance as yf +load_dotenv() + + +llm = AzureChatOpenAI( + azure_endpoint=os.environ['AZURE_OPENAI_ENDPOINT'], + azure_deployment=os.environ['AZURE_OPENAI_DEPLOYMENT_NAME'], + openai_api_version=os.environ['AZURE_OPENAI_API_VERSION'], + openai_api_key=os.environ['AZURE_OPENAI_API_KEY'] +) + + + +class QueryFields(BaseModel): + symbol: str = Field(..., description="Stock ticker symbol (e.g., TSLA, AAPL).") + timeframe: str = Field(..., description="Time period (e.g., '1d', '1mo', '1y').") + action: str = Field(..., description="Action to be performed (e.g., 'fetch', 'plot').") + +class QueryAnalysisOutput(BaseModel): + result: QueryFields +class StockAnalysisState(TypedDict): + query: str + parsed_output: QueryAnalysisOutput + generated_code: Optional[str] + execution_result: Optional[str] + + + +def query_parser_node(state: StockAnalysisState): + query = state["query"] + prompt = """You are a Stock Data Analyst. Extract stock details from this user query: {query}. + + """ + finalprompt=prompt.format(query=query) + llm_with_struc=llm.with_structured_output(QueryAnalysisOutput) + response = llm_with_struc.invoke(finalprompt) + + return {"parsed_output": response} + +def code_writer_node(state: StockAnalysisState): + parsed = state["parsed_output"] + if isinstance(parsed, dict): + raise NodeInterrupt("recieved wrong type") + fprompt = """You are a Senior Python Developer. Generate code to {action} the stock data. + Stock: {symbol} + Timeframe: {timeframe} + + Use yfinance, pandas, and matplotlib libraries. Output should be a clean, executable .py Python script for stock visualization without explanations or AI-generated messages—just the direct script content. without ''' or any code blockers + """ + action=parsed.result.action + symbol=parsed.result.symbol + time=parsed.result.timeframe + ffprompt=fprompt.format(action=action,symbol=symbol,timeframe=time) + code = llm.invoke(ffprompt) + return {"generated_code": code} + + +def code_result(state: StockAnalysisState): + + generated_code = state["generated_code"] + try: + # Execute the generated code in a controlled environment + exec_globals = {} + exec(generated_code.content, exec_globals) + return {"execution_result": "Code executed successfully"} + except Exception as e: + return {"execution_result": f"Execution failed: {str(e)}"} + + +graph = StateGraph(StockAnalysisState) + +graph.add_node("QueryParser", query_parser_node) +graph.add_node("CodeWriter", code_writer_node) +graph.add_node("CodeExecutor", code_result) + + +graph.add_edge(START,"QueryParser") +graph.add_edge("QueryParser", "CodeWriter") +graph.add_edge("CodeWriter", "CodeExecutor") +graph.add_edge("CodeExecutor", END) + + +workflow = graph.compile() + +#visual representation of our graph +#display(Image(workflow.get_graph(xray=1).draw_mermaid_png())) + + +# Function to be wrapped inside MCP tool +def run_financial_analysis(query): + result = workflow.invoke({"query": query}) + + return result["generated_code"].content + +if __name__ == "__main__": + res=run_financial_analysis("Plot YTD stock gain of Tesla") + print(res) diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/graph.png b/financial-analyst-deepseek/financial-analyst-langgraph/graph.png new file mode 100644 index 000000000..aaecff22b Binary files /dev/null and b/financial-analyst-deepseek/financial-analyst-langgraph/graph.png differ diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/requirements.txt b/financial-analyst-deepseek/financial-analyst-langgraph/requirements.txt new file mode 100644 index 000000000..66e9e4118 --- /dev/null +++ b/financial-analyst-deepseek/financial-analyst-langgraph/requirements.txt @@ -0,0 +1,10 @@ +langgraph +langchain +langchain-core +langchain-openai +pydantic +ipython +python-dotenv +yfinance +matplotlib +mcp diff --git a/financial-analyst-deepseek/financial-analyst-langgraph/server.py b/financial-analyst-deepseek/financial-analyst-langgraph/server.py new file mode 100644 index 000000000..b3c459df0 --- /dev/null +++ b/financial-analyst-deepseek/financial-analyst-langgraph/server.py @@ -0,0 +1,63 @@ +from mcp.server.fastmcp import FastMCP +from finance_langgraph import run_financial_analysis + +# create FastMCP instance +mcp = FastMCP("financial-analyst") + +@mcp.tool() +def analyze_stock(query: str) -> str: + """ + Analyzes stock market data based on the query and generates executable Python code for analysis and visualization. + Returns a formatted Python script ready for execution. + + The query is a string that must contain the stock symbol (e.g., TSLA, AAPL, NVDA, etc.), + timeframe (e.g., 1d, 1mo, 1y), and action to perform (e.g., plot, analyze, compare). + + Example queries: + - "Show me Tesla's stock performance over the last 3 months" + - "Compare Apple and Microsoft stocks for the past year" + - "Analyze the trading volume of Amazon stock for the last month" + + Args: + query (str): The query to analyze the stock market data. + + Returns: + str: A nicely formatted python code as a string. + """ + try: + result = run_financial_analysis(query) + return result + except Exception as e: + return f"Error: {e}" + + +@mcp.tool() +def save_code(code: str) -> str: + """ + Expects a nicely formatted, working and executable python code as input in form of a string. + Save the given code to a file stock_analysis.py, make sure the code is a valid python file, nicely formatted and ready to execute. + + Args: + code (str): The nicely formatted, working and executable python code as string. + + Returns: + str: A message indicating the code was saved successfully. + """ + try: + with open('stock_analysis.py', 'w') as f: + f.write(code) + return "Code saved to stock_analysis.py" + except Exception as e: + return f"Error: {e}" + +@mcp.tool() +def run_code_and_show_plot() -> str: + """ + Run the code in stock_analysis.py and generate the plot + """ + with open('stock_analysis.py', 'r') as f: + exec(f.read()) + +# Run the server locally +if __name__ == "__main__": + mcp.run(transport='stdio') \ No newline at end of file