{"product_id":"financial-data-analyst-phan-tich-dữ-liệu-va-biểu-dồ-tự-dộng","title":"Financial Data Analyst — Phân tích dữ liệu và biểu đồ tự động","description":"\n\u003cp\u003ePhân tích tài chính truyền thống đòi hỏi analyst phải viết code pandas, tạo biểu đồ matplotlib, và soạn báo cáo — mỗi bước tốn nhiều thời gian. \u003cstrong\u003eFinancial Data Analyst Agent\u003c\/strong\u003e tự động hóa toàn bộ pipeline này: nhận câu hỏi bằng ngôn ngữ tự nhiên, tự viết và thực thi code phân tích, sinh biểu đồ, và tổng hợp báo cáo.\u003c\/p\u003e\n\n\u003cp\u003eBài viết này xây dựng agent phân tích cổ phiếu và portfolio với Claude sonnet làm coding engine.\u003c\/p\u003e\n\n\u003ch2\u003eKiến trúc: Code Execution Agent\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eUser: \"Phan tich co phieu VNM trong 6 thang qua\"\n      |\n      v\n[Claude: Viet code pandas de phan tich]\n      |\n      v\n[Execute code trong sandbox]\n      |\n      v\n[Thu thap ket qua + output charts]\n      |\n      v\n[Claude: Interpret ket qua, viet bao cao]\n      |\n      v\nReport + Charts\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eĐiểm mấu chốt: Claude không chỉ sinh code — nó còn \u003cstrong\u003ethực thi code đó\u003c\/strong\u003e, đọc kết quả, và diễn giải ý nghĩa tài chính. Đây là pattern \"code interpreter\" tương tự ChatGPT Code Interpreter.\u003c\/p\u003e\n\n\u003ch2\u003eSetup môi trường\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003epip install anthropic pandas numpy matplotlib yfinance scipy\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eCấu trúc project:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003efinancial-analyst\/\n  agent.py          -- Agent chính\n  code_executor.py  -- Sandbox thực thi code\n  data_tools.py     -- Lấy dữ liệu tài chính\n  output\/           -- Charts và reports được lưu ở đây\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eCode Executor — Sandbox an toàn\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003e# code_executor.py\nimport sys\nimport io\nimport traceback\nimport matplotlib\nmatplotlib.use('Agg')  # Non-interactive backend\nimport matplotlib.pyplot as plt\nimport base64\nimport os\n\nALLOWED_IMPORTS = {\n    'pandas', 'numpy', 'matplotlib', 'matplotlib.pyplot',\n    'scipy', 'math', 'statistics', 'json', 'datetime'\n}\n\ndef execute_python(code: str, context: dict = None) -\u0026gt; dict:\n    \"\"\"\n    Thuc thi Python code trong sandbox.\n    Tra ve: output text, loi, va danh sach charts (base64).\n    \"\"\"\n    if context is None:\n        context = {}\n\n    # Capture stdout\n    old_stdout = sys.stdout\n    sys.stdout = captured_output = io.StringIO()\n\n    charts = []\n    errors = None\n\n    try:\n        # Inject san variables tien ich\n        exec_globals = {\n            '__builtins__': {\n                'print': print,\n                'range': range,\n                'len': len,\n                'list': list,\n                'dict': dict,\n                'str': str,\n                'int': int,\n                'float': float,\n                'bool': bool,\n                'round': round,\n                'sorted': sorted,\n                'enumerate': enumerate,\n                'zip': zip,\n                'min': min,\n                'max': max,\n                'sum': sum,\n                'abs': abs,\n            }\n        }\n\n        # Cho phep import thu vien an toan\n        import pandas as pd\n        import numpy as np\n        import matplotlib.pyplot as plt\n\n        exec_globals.update({\n            'pd': pd,\n            'np': np,\n            'plt': plt,\n            **context\n        })\n\n        # Thuc thi code\n        exec(code, exec_globals)\n\n        # Thu thap tat ca charts\n        for fig_num in plt.get_fignums():\n            fig = plt.figure(fig_num)\n            buf = io.BytesIO()\n            fig.savefig(buf, format='png', dpi=150, bbox_inches='tight')\n            buf.seek(0)\n            chart_b64 = base64.b64encode(buf.read()).decode()\n            charts.append(chart_b64)\n            plt.close(fig)\n\n    except Exception as e:\n        errors = traceback.format_exc()\n\n    finally:\n        sys.stdout = old_stdout\n        plt.close('all')\n\n    output = captured_output.getvalue()\n\n    return {\n        \"output\": output,\n        \"errors\": errors,\n        \"charts\": charts,\n        \"charts_count\": len(charts),\n        \"success\": errors is None\n    }\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eData Tools — Lấy dữ liệu tài chính thực\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003e# data_tools.py\nimport json\n\ndef get_stock_data(ticker: str, period: str = \"6mo\") -\u0026gt; str:\n    \"\"\"\n    Lay du lieu lich su co phieu tu Yahoo Finance.\n    period: 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, ytd, max\n    \"\"\"\n    try:\n        import yfinance as yf\n        stock = yf.Ticker(ticker)\n        hist = stock.history(period=period)\n\n        if hist.empty:\n            return json.dumps({\"error\": f\"Khong tim thay du lieu cho {ticker}\"})\n\n        # Chuyen sang JSON-friendly format\n        data = {\n            \"ticker\": ticker,\n            \"period\": period,\n            \"records\": len(hist),\n            \"start_date\": str(hist.index[0].date()),\n            \"end_date\": str(hist.index[-1].date()),\n            \"latest_close\": round(float(hist['Close'].iloc[-1]), 2),\n            \"data_csv\": hist.to_csv()\n        }\n        return json.dumps(data, ensure_ascii=False)\n\n    except Exception as e:\n        return json.dumps({\"error\": str(e)})\n\n\ndef get_portfolio_data(holdings: list) -\u0026gt; str:\n    \"\"\"\n    Lay du lieu cho nhieu co phieu.\n    holdings: [{\"ticker\": \"VNM\", \"shares\": 100, \"avg_cost\": 85000}, ...]\n    \"\"\"\n    try:\n        import yfinance as yf\n        portfolio = []\n\n        for h in holdings:\n            ticker = h[\"ticker\"]\n            shares = h[\"shares\"]\n            avg_cost = h.get(\"avg_cost\", 0)\n\n            stock = yf.Ticker(ticker)\n            info = stock.fast_info\n\n            current_price = round(float(info.last_price or 0), 2)\n            market_value = current_price * shares\n            cost_basis = avg_cost * shares\n            pnl = market_value - cost_basis\n            pnl_pct = (pnl \/ cost_basis * 100) if cost_basis \u0026gt; 0 else 0\n\n            portfolio.append({\n                \"ticker\": ticker,\n                \"shares\": shares,\n                \"current_price\": current_price,\n                \"market_value\": round(market_value, 2),\n                \"cost_basis\": round(cost_basis, 2),\n                \"pnl\": round(pnl, 2),\n                \"pnl_pct\": round(pnl_pct, 2)\n            })\n\n        total_value = sum(p[\"market_value\"] for p in portfolio)\n        total_pnl = sum(p[\"pnl\"] for p in portfolio)\n\n        return json.dumps({\n            \"holdings\": portfolio,\n            \"total_market_value\": round(total_value, 2),\n            \"total_pnl\": round(total_pnl, 2),\n            \"total_pnl_pct\": round(total_pnl \/ (total_value - total_pnl) * 100, 2) if total_value \u0026gt; total_pnl else 0\n        }, ensure_ascii=False)\n\n    except Exception as e:\n        return json.dumps({\"error\": str(e)})\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTool Schemas và Agent\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003e# agent.py\nimport anthropic\nimport json\nfrom code_executor import execute_python\nfrom data_tools import get_stock_data, get_portfolio_data\n\nclient = anthropic.Anthropic()\n\nanalyst_tools = [\n    {\n        \"name\": \"execute_python\",\n        \"description\": (\n            \"Thuc thi Python code de phan tich du lieu tai chinh. \"\n            \"Co san: pandas (pd), numpy (np), matplotlib (plt). \"\n            \"Dung plt.figure() de tao bieu do. Dung print() de hien thi ket qua. \"\n            \"Bien 'stock_data' co san neu da get_stock_data truoc.\"\n        ),\n        \"input_schema\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"code\": {\n                    \"type\": \"string\",\n                    \"description\": \"Python code can thuc thi\"\n                }\n            },\n            \"required\": [\"code\"]\n        }\n    },\n    {\n        \"name\": \"get_stock_data\",\n        \"description\": \"Lay du lieu lich su gia co phieu tu Yahoo Finance\",\n        \"input_schema\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"ticker\": {\n                    \"type\": \"string\",\n                    \"description\": \"Ma co phieu, vi du: AAPL, TSLA, VNM.VN\"\n                },\n                \"period\": {\n                    \"type\": \"string\",\n                    \"description\": \"Khoang thoi gian: 1mo, 3mo, 6mo, 1y, 2y, max\",\n                    \"enum\": [\"1mo\", \"3mo\", \"6mo\", \"1y\", \"2y\", \"5y\", \"max\"]\n                }\n            },\n            \"required\": [\"ticker\"]\n        }\n    },\n    {\n        \"name\": \"get_portfolio_data\",\n        \"description\": \"Lay du lieu hien tai cua danh muc dau tu\",\n        \"input_schema\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"holdings\": {\n                    \"type\": \"array\",\n                    \"description\": \"Danh sach co phieu nam giu\",\n                    \"items\": {\n                        \"type\": \"object\",\n                        \"properties\": {\n                            \"ticker\": {\"type\": \"string\"},\n                            \"shares\": {\"type\": \"number\"},\n                            \"avg_cost\": {\"type\": \"number\"}\n                        }\n                    }\n                }\n            },\n            \"required\": [\"holdings\"]\n        }\n    }\n]\n\nANALYST_SYSTEM = \"\"\"Ban la mot chuyen gia phan tich tai chinh co kinh nghiem.\nKhi duoc hoi, hay:\n1. Thu thap du lieu can thiet bang tools\n2. Viet va thuc thi code phan tich chi tiet\n3. Tao bieu do truc quan khi phu hop\n4. Dien giai ket qua theo goc do tai chinh, khong chi mo ta so lieu\n5. Dua ra nhan xet va khuyen nghi thuc te\n\nLuon giai thich y nghia cua chi so, khong chi liet ke so lieu.\"\"\"\n\n\ndef run_financial_analyst(question: str) -\u0026gt; dict:\n    messages = [{\"role\": \"user\", \"content\": question}]\n    all_charts = []\n    stock_context = {}\n\n    for _ in range(20):\n        response = client.messages.create(\n            model=\"claude-sonnet-4-5\",\n            max_tokens=8192,\n            system=ANALYST_SYSTEM,\n            tools=analyst_tools,\n            messages=messages\n        )\n\n        messages.append({\"role\": \"assistant\", \"content\": response.content})\n\n        if response.stop_reason == \"end_turn\":\n            final_text = next(\n                (b.text for b in response.content if hasattr(b, \"text\")), \"\"\n            )\n            return {\n                \"analysis\": final_text,\n                \"charts\": all_charts,\n                \"charts_count\": len(all_charts)\n            }\n\n        tool_results = []\n        for block in response.content:\n            if block.type != \"tool_use\":\n                continue\n\n            if block.name == \"get_stock_data\":\n                result = get_stock_data(**block.input)\n                data = json.loads(result)\n                # Luu CSV vao context de code co the dung\n                if \"data_csv\" in data:\n                    stock_context[\"_last_csv\"] = data[\"data_csv\"]\n                tool_results.append({\n                    \"type\": \"tool_result\",\n                    \"tool_use_id\": block.id,\n                    \"content\": result\n                })\n\n            elif block.name == \"get_portfolio_data\":\n                result = get_portfolio_data(**block.input)\n                tool_results.append({\n                    \"type\": \"tool_result\",\n                    \"tool_use_id\": block.id,\n                    \"content\": result\n                })\n\n            elif block.name == \"execute_python\":\n                # Inject CSV data neu co\n                code = block.input[\"code\"]\n                if \"_last_csv\" in stock_context:\n                    # Them code load CSV vao dau\n                    load_code = (\n                        \"import io\n\"\n                        \"_csv_data = '''\" + stock_context[\"_last_csv\"] + \"'''\n\"\n                        \"stock_data = pd.read_csv(io.StringIO(_csv_data), index_col=0, parse_dates=True)\n\"\n                    )\n                    code = load_code + code\n\n                exec_result = execute_python(code)\n                all_charts.extend(exec_result.get(\"charts\", []))\n\n                result_str = exec_result[\"output\"]\n                if exec_result[\"errors\"]:\n                    result_str += \"\nLOI:\n\" + exec_result[\"errors\"]\n                if exec_result[\"charts_count\"] \u0026gt; 0:\n                    result_str += f\"\n[Da tao {exec_result['charts_count']} bieu do]\"\n\n                tool_results.append({\n                    \"type\": \"tool_result\",\n                    \"tool_use_id\": block.id,\n                    \"content\": result_str\n                })\n\n        messages.append({\"role\": \"user\", \"content\": tool_results})\n\n    return {\"analysis\": \"Timeout\", \"charts\": all_charts, \"charts_count\": len(all_charts)}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eDemo: Phân tích cổ phiếu Apple\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eresult = run_financial_analyst(\n    \"Phan tich co phieu AAPL trong 6 thang qua. \"\n    \"Tinh: return, volatility, Sharpe ratio, va ve bieu do gia + volume.\"\n)\n\nprint(result[\"analysis\"])\nprint(f\"Da tao {result['charts_count']} bieu do\")\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003cp\u003eClaude sẽ tự động sinh và chạy code như sau:\u003c\/p\u003e\n\n\u003cpre\u003e\u003ccode\u003e# Code Claude tu sinh va thuc thi:\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# stock_data da duoc inject tu get_stock_data()\nclose = stock_data['Close']\nreturns = close.pct_change().dropna()\n\n# Tinh chi so\ntotal_return = (close.iloc[-1] \/ close.iloc[0] - 1) * 100\nvolatility = returns.std() * np.sqrt(252) * 100\nsharpe = (returns.mean() \/ returns.std()) * np.sqrt(252)\n\nprint(f\"Total Return: {total_return:.2f}%\")\nprint(f\"Annualized Volatility: {volatility:.2f}%\")\nprint(f\"Sharpe Ratio: {sharpe:.2f}\")\n\n# Bieu do\nfig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))\nax1.plot(close.index, close.values)\nax1.set_title('AAPL - Gia co phieu')\nax2.bar(stock_data.index, stock_data['Volume'])\nax2.set_title('Volume')\nplt.tight_layout()\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eDemo: Portfolio Review\u003c\/h2\u003e\n\n\u003cpre\u003e\u003ccode\u003eportfolio_result = run_financial_analyst(\n    \"Review danh muc cua toi: AAPL 50 co phieu (mua gia 150), \"\n    \"MSFT 30 co phieu (mua gia 380), GOOGL 20 co phieu (mua gia 140). \"\n    \"Tinh P\u0026amp;L, phan bo danh muc, va khuyen nghi re-balance.\"\n)\n\nprint(portfolio_result[\"analysis\"])\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTổng kết: Khả năng của Financial Analyst Agent\u003c\/h2\u003e\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n\u003cth\u003eTính năng\u003c\/th\u003e\n\u003cth\u003eCông nghệ\u003c\/th\u003e\n\u003cth\u003eỨng dụng\u003c\/th\u003e\n\u003c\/tr\u003e\n  \u003c\/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n\u003ctd\u003eStock Analysis\u003c\/td\u003e\n\u003ctd\u003eyfinance + pandas\u003c\/td\u003e\n\u003ctd\u003eHistorical data, returns, volatility\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eVisualization\u003c\/td\u003e\n\u003ctd\u003ematplotlib\u003c\/td\u003e\n\u003ctd\u003ePrice charts, volume, heatmaps\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003ePortfolio Review\u003c\/td\u003e\n\u003ctd\u003epandas + numpy\u003c\/td\u003e\n\u003ctd\u003eP\u0026amp;L, allocation, Sharpe ratio\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eCode Execution\u003c\/td\u003e\n\u003ctd\u003ePython sandbox\u003c\/td\u003e\n\u003ctd\u003eTự sinh và chạy analysis code\u003c\/td\u003e\n\u003c\/tr\u003e\n    \u003ctr\u003e\n\u003ctd\u003eReport Generation\u003c\/td\u003e\n\u003ctd\u003eClaude sonnet\u003c\/td\u003e\n\u003ctd\u003eDiễn giải kết quả theo ngôn ngữ tự nhiên\u003c\/td\u003e\n\u003c\/tr\u003e\n  \u003c\/tbody\u003e\n\u003c\/table\u003e\n\n\u003cp\u003eFinancial Analyst Agent cho thấy sức mạnh của pattern \"LLM + Code Execution\": thay vì dùng pre-built tools cứng nhắc, Claude tự viết code phù hợp với từng câu hỏi cụ thể — linh hoạt như một data scientist thực sự.\u003c\/p\u003e\n\n\u003cp\u003eMuốn mở rộng? Thêm dữ liệu thực từ SSI, VPS, hoặc Bloomberg API; kết hợp với \u003ca href=\"\/collections\/nang-cao\"\u003eCustomer Support Agent\u003c\/a\u003e để tạo robo-advisor; hoặc đọc về \u003ca href=\"\/collections\/nang-cao\"\u003eLLM Agent từ đầu\u003c\/a\u003e để nắm vững kiến trúc nền tảng.\u003c\/p\u003e\n\n\n\u003chr\u003e\n\u003ch3\u003eBài viết liên quan\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"\/products\/claude-cho-tai-chinh-t%E1%BB%95ng-quan-plugin\"\u003eClaude cho Tài chính: Tổng quan Plugin\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/claude-cho-finance-qu%E1%BA%A3n-ly-close-s%E1%BB%95-k%E1%BA%BF-toan\"\u003eClaude cho Finance: Quản lý close sổ kế toán\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/claude-cho-finance-phan-tich-bao-cao-tai-chinh\"\u003eClaude cho Finance: Phân tích báo cáo tài chính\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/customer-support-agent-chatbot-h%E1%BB%97-tr%E1%BB%A3-production-grade\"\u003eCustomer Support Agent — Chatbot hỗ trợ production-grade\u003c\/a\u003e\u003c\/li\u003e\n\u003cli\u003e\u003ca href=\"\/products\/claude-cho-legal-danh-gia-r%E1%BB%A7i-ro-phap-ly\"\u003eClaude cho Legal: Đánh giá rủi ro pháp lý\u003c\/a\u003e\u003c\/li\u003e\n\u003c\/ul\u003e","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47721912533204,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/financial-data-analyst-phan-tich-d_-li_u-va-bi_u-d_-t_-d_ng_33f6d0c1-c006-4683-abe4-1797bf080b4d.jpg?v=1774521844","url":"https:\/\/claude.vn\/products\/financial-data-analyst-phan-tich-d%e1%bb%af-li%e1%bb%87u-va-bi%e1%bb%83u-d%e1%bb%93-t%e1%bb%b1-d%e1%bb%99ng","provider":"CLAUDE.VN","version":"1.0","type":"link"}