Trung cấpHướng dẫnClaude APINguồn: Anthropic

Claude Skills cho Tài chính — Dashboard, portfolio, phân tích

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Hành động cụ thể: pip install anthropic pandas numpy yfinance matplotlib plotly openpyxl. Phần này hướng dẫn bạn cách triển khai thực tế, không chỉ lý thuyết suông.
  2. 2 Một điều ít người đề cập: import anthropic import json import yfinance as yf import pandas as pd import numpy as np from datetime import. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
  3. 3 Điểm nhấn quan trọng: import plotly.graphobjects as go from plotly.subplots import makesubplots def createfinancialdashboardportfoliodata:. Đây là phần mang lại giá trị thực tiễn cao nhất trong toàn bài viết.
  4. 4 Tận dụng Claude hiệu quả: def rundcfanalysiscompanydata: dict -> dict: """Discounted Cash Flow analysis với Claude""" response = — mẹo quan trọng là cung cấp đủ ngữ cảnh để AI trả về kết quả chính xác hơn 80% so với prompt chung chung.
  5. 5 Thành thật mà nói: def generatemonthlyreportportfolio: dict, month: str -> str: """Tạo báo cáo tháng đầy đủ: phân tích + Excel +. Phương pháp này hiệu quả trong hầu hết trường hợp, nhưng bạn cần điều chỉnh cho phù hợp ngữ cảnh riêng.
a blue button with a white arrow on it

Phân tích tài chính truyền thống đòi hỏi chuyên gia với Excel phức tạp, Python scripts tùy chỉnh, và nhiều giờ làm việc thủ công. Claude kết hợp với financial libraries thay đổi hoàn toàn điều này — từ việc giải thích dữ liệu đến tự động tạo báo cáo chuyên sâu.

Setup môi trường

pip install anthropic pandas numpy yfinance matplotlib plotly openpyxl

Module 1: Portfolio Analyzer

import anthropic
import json
import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

client = anthropic.Anthropic()

class PortfolioAnalyzer:
    def __init__(self):
        self.client = anthropic.Anthropic()

    def analyze_portfolio(self, holdings: dict) -> dict:
        """
        holdings = {
            "AAPL": {"shares": 100, "avg_cost": 150.0},
            "MSFT": {"shares": 50, "avg_cost": 280.0},
            "GOOGL": {"shares": 20, "avg_cost": 2800.0}
        }
        """
        # Fetch market data
        market_data = self._fetch_market_data(list(holdings.keys()))

        # Calculate portfolio metrics
        portfolio_metrics = self._calculate_metrics(holdings, market_data)

        # Claude phân tích và đưa ra insights
        analysis = self._ai_analysis(portfolio_metrics)

        return {
            "metrics": portfolio_metrics,
            "analysis": analysis,
            "recommendations": self._generate_recommendations(portfolio_metrics, analysis)
        }

    def _fetch_market_data(self, symbols: list) -> dict:
        data = {}
        end_date = datetime.now()
        start_date = end_date - timedelta(days=365)

        for symbol in symbols:
            try:
                ticker = yf.Ticker(symbol)
                hist = ticker.history(start=start_date, end=end_date)
                info = ticker.info

                data[symbol] = {
                    "current_price": hist['Close'].iloc[-1] if not hist.empty else 0,
                    "price_52w_high": hist['Close'].max() if not hist.empty else 0,
                    "price_52w_low": hist['Close'].min() if not hist.empty else 0,
                    "ytd_return": self._calculate_ytd_return(hist),
                    "volatility": hist['Close'].pct_change().std() * np.sqrt(252) * 100 if not hist.empty else 0,
                    "pe_ratio": info.get('trailingPE', 'N/A'),
                    "sector": info.get('sector', 'Unknown'),
                    "prices_30d": hist['Close'].tail(30).tolist() if not hist.empty else []
                }
            except Exception as e:
                data[symbol] = {"error": str(e), "current_price": 0}

        return data

    def _calculate_ytd_return(self, hist: pd.DataFrame) -> float:
        if hist.empty:
            return 0
        year_start = hist[hist.index.year == datetime.now().year]
        if year_start.empty:
            return 0
        first_price = year_start['Close'].iloc[0]
        last_price = hist['Close'].iloc[-1]
        return ((last_price - first_price) / first_price) * 100

    def _calculate_metrics(self, holdings: dict, market_data: dict) -> dict:
        total_cost = 0
        total_value = 0
        positions = []

        for symbol, holding in holdings.items():
            mdata = market_data.get(symbol, {})
            shares = holding["shares"]
            avg_cost = holding["avg_cost"]
            current_price = mdata.get("current_price", 0)

            cost_basis = shares * avg_cost
            market_value = shares * current_price
            gain_loss = market_value - cost_basis
            gain_loss_pct = ((current_price - avg_cost) / avg_cost * 100) if avg_cost > 0 else 0

            total_cost += cost_basis
            total_value += market_value

            positions.append({
                "symbol": symbol,
                "shares": shares,
                "avg_cost": avg_cost,
                "current_price": current_price,
                "market_value": market_value,
                "cost_basis": cost_basis,
                "gain_loss": gain_loss,
                "gain_loss_pct": round(gain_loss_pct, 2),
                "weight": 0,  # Will calculate after totals
                "sector": mdata.get("sector", "Unknown"),
                "pe_ratio": mdata.get("pe_ratio", "N/A"),
                "ytd_return": mdata.get("ytd_return", 0),
                "volatility": mdata.get("volatility", 0)
            })

        # Calculate weights
        for pos in positions:
            pos["weight"] = (pos["market_value"] / total_value * 100) if total_value > 0 else 0

        # Portfolio-level metrics
        portfolio_return = ((total_value - total_cost) / total_cost * 100) if total_cost > 0 else 0

        # Sector allocation
        sector_allocation = {}
        for pos in positions:
            sector = pos["sector"]
            sector_allocation[sector] = sector_allocation.get(sector, 0) + pos["weight"]

        return {
            "total_cost": total_cost,
            "total_value": total_value,
            "total_gain_loss": total_value - total_cost,
            "portfolio_return_pct": round(portfolio_return, 2),
            "positions": positions,
            "sector_allocation": sector_allocation,
            "num_positions": len(positions),
            "largest_position": max(positions, key=lambda x: x["weight"])["symbol"] if positions else None
        }

    def _ai_analysis(self, metrics: dict) -> str:
        positions_summary = "
".join([
            f"- {p['symbol']}: {p['weight']:.1f}% weight, {p['gain_loss_pct']:+.1f}% return, volatility {p['volatility']:.1f}%"
            for p in metrics["positions"]
        ])

        response = self.client.messages.create(
            model="claude-opus-4-5",
            max_tokens=2000,
            system="You are a senior portfolio manager and financial analyst. Provide clear, actionable analysis.",
            messages=[{
                "role": "user",
                "content": f"""Analyze this investment portfolio:

Total Value: ${metrics['total_value']:,.2f}
Total Return: {metrics['portfolio_return_pct']:+.2f}%
Number of Positions: {metrics['num_positions']}

Positions:
{positions_summary}

Sector Allocation:
{json.dumps(metrics['sector_allocation'], indent=2)}

Provide analysis on:
1. Portfolio diversification (concentrated? well-diversified?)
2. Risk assessment (high volatility positions, sector concentration)
3. Performance highlights (winners and laggards)
4. Key risks to watch
5. Overall portfolio health score (1-10) with brief explanation"""
            }]
        )
        return response.content[0].text

    def _generate_recommendations(self, metrics: dict, analysis: str) -> list:
        response = self.client.messages.create(
            model="claude-haiku-4-5",
            max_tokens=1000,
            messages=[{
                "role": "user",
                "content": f"""Based on this portfolio analysis, provide 3-5 specific, actionable recommendations.

Analysis:
{analysis}

Portfolio Stats:
- Total Return: {metrics['portfolio_return_pct']:+.2f}%
- Positions: {metrics['num_positions']}
- Sectors: {list(metrics['sector_allocation'].keys())}

Format each recommendation as:
ACTION: [BUY/SELL/HOLD/REBALANCE]
TICKER: [if applicable]
RATIONALE: [1-2 sentences]
PRIORITY: [HIGH/MEDIUM/LOW]"""
            }]
        )
        return response.content[0].text.strip().split("

")

Module 2: Financial Dashboard Generator

import plotly.graph_objects as go
from plotly.subplots import make_subplots

def create_financial_dashboard(portfolio_data: dict, output_html: str):
    """Tạo interactive HTML dashboard với Plotly"""

    positions = portfolio_data["metrics"]["positions"]
    sector_alloc = portfolio_data["metrics"]["sector_allocation"]

    fig = make_subplots(
        rows=2, cols=2,
        subplot_titles=[
            "Portfolio Composition",
            "Sector Allocation",
            "Gain/Loss by Position",
            "Risk vs Return"
        ],
        specs=[
            [{"type": "pie"}, {"type": "pie"}],
            [{"type": "bar"}, {"type": "scatter"}]
        ]
    )

    # 1. Portfolio composition (by market value)
    fig.add_trace(
        go.Pie(
            labels=[p["symbol"] for p in positions],
            values=[p["market_value"] for p in positions],
            name="Portfolio"
        ),
        row=1, col=1
    )

    # 2. Sector allocation
    fig.add_trace(
        go.Pie(
            labels=list(sector_alloc.keys()),
            values=list(sector_alloc.values()),
            name="Sectors"
        ),
        row=1, col=2
    )

    # 3. Gain/Loss bar chart
    colors = ['green' if p["gain_loss"] >= 0 else 'red' for p in positions]
    fig.add_trace(
        go.Bar(
            x=[p["symbol"] for p in positions],
            y=[p["gain_loss"] for p in positions],
            marker_color=colors,
            name="Gain/Loss"
        ),
        row=2, col=1
    )

    # 4. Risk vs Return scatter
    fig.add_trace(
        go.Scatter(
            x=[p["volatility"] for p in positions],
            y=[p["gain_loss_pct"] for p in positions],
            mode='markers+text',
            text=[p["symbol"] for p in positions],
            textposition="top center",
            marker=dict(
                size=[p["weight"] * 2 for p in positions],  # Size by weight
                color=[p["gain_loss"] for p in positions],
                colorscale='RdYlGn',
                showscale=True
            ),
            name="Risk/Return"
        ),
        row=2, col=2
    )

    fig.update_layout(
        title=f"Portfolio Dashboard — Total Value: ${portfolio_data['metrics']['total_value']:,.2f}",
        height=800,
        showlegend=False
    )

    fig.write_html(output_html)
    print(f"Dashboard saved to: {output_html}")
    return output_html

Module 3: Financial Modeling với Claude

def run_dcf_analysis(company_data: dict) -> dict:
    """Discounted Cash Flow analysis với Claude"""

    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=3000,
        system="You are a CFA-level financial analyst expert in DCF valuation.",
        messages=[{
            "role": "user",
            "content": f"""Perform a DCF (Discounted Cash Flow) analysis for:

Company: {company_data.get('name')}
Industry: {company_data.get('industry')}
Current Revenue: ${company_data.get('revenue', 0):,.0f}
Revenue Growth (3-year avg): {company_data.get('revenue_growth', 0):.1f}%
Operating Margin: {company_data.get('operating_margin', 0):.1f}%
Current P/E: {company_data.get('pe_ratio', 'N/A')}
Shares Outstanding: {company_data.get('shares', 0):,.0f}

Provide:
1. 5-year revenue and FCF projections (base/bull/bear scenarios)
2. Discount rate (WACC) estimate with reasoning
3. Terminal value calculation
4. Intrinsic value per share (all 3 scenarios)
5. Margin of safety at current price: ${company_data.get('current_price', 0):.2f}
6. Investment verdict: UNDERVALUED / FAIRLY VALUED / OVERVALUED

Format key numbers clearly."""
        }]
    )
    return {"analysis": response.content[0].text}

Tích hợp đầy đủ: Monthly Report Generator

def generate_monthly_report(portfolio: dict, month: str) -> str:
    """Tạo báo cáo tháng đầy đủ: phân tích + Excel + Dashboard"""

    analyzer = PortfolioAnalyzer()

    # 1. Phân tích portfolio
    print("Analyzing portfolio...")
    analysis_result = analyzer.analyze_portfolio(portfolio)

    # 2. Tạo Excel report
    import openpyxl
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = f"Portfolio {month}"

    headers = ["Symbol", "Shares", "Avg Cost", "Current Price",
               "Market Value", "Gain/Loss", "Return%", "Weight%", "Sector"]
    for col, h in enumerate(headers, 1):
        ws.cell(row=1, column=col, value=h)

    for row, pos in enumerate(analysis_result["metrics"]["positions"], 2):
        ws.cell(row=row, column=1, value=pos["symbol"])
        ws.cell(row=row, column=2, value=pos["shares"])
        ws.cell(row=row, column=3, value=pos["avg_cost"])
        ws.cell(row=row, column=4, value=pos["current_price"])
        ws.cell(row=row, column=5, value=pos["market_value"])
        ws.cell(row=row, column=6, value=pos["gain_loss"])
        ws.cell(row=row, column=7, value=pos["gain_loss_pct"])
        ws.cell(row=row, column=8, value=round(pos["weight"], 2))
        ws.cell(row=row, column=9, value=pos["sector"])

    excel_path = f"/tmp/portfolio_{month}.xlsx"
    wb.save(excel_path)

    # 3. Tạo HTML dashboard
    dashboard_path = f"/tmp/dashboard_{month}.html"
    create_financial_dashboard(analysis_result, dashboard_path)

    # 4. AI Summary
    summary_response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=500,
        messages=[{
            "role": "user",
            "content": f"""Write a brief monthly portfolio summary for {month}:

Performance: {analysis_result['metrics']['portfolio_return_pct']:+.2f}%
Total Value: ${analysis_result['metrics']['total_value']:,.2f}

Analysis highlights:
{analysis_result['analysis'][:500]}

Write 3-4 sentences suitable for an executive briefing."""
        }]
    )

    return {
        "excel": excel_path,
        "dashboard": dashboard_path,
        "summary": summary_response.content[0].text,
        "recommendations": analysis_result["recommendations"]
    }

# Chạy report
holdings = {
    "AAPL": {"shares": 100, "avg_cost": 150.0},
    "MSFT": {"shares": 50, "avg_cost": 280.0},
    "VNM.VN": {"shares": 1000, "avg_cost": 75.0}
}
report = generate_monthly_report(holdings, "2025-03")
print(f"Report generated: {report['summary']}")

Tổng kết

Với Claude + Python financial libraries, bạn có thể xây dựng công cụ phân tích tài chính mạnh mẽ:

  • Portfolio Analyzer — metrics tự động + AI insights
  • Dashboard Generator — interactive charts với Plotly
  • DCF Modeling — valuation analysis với Claude làm financial analyst
  • Monthly Reports — Excel + dashboard + executive summary tự động

Khám phá tiếp: Tạo Custom Skills cho Claude để đóng gói các tools này thành skills tái sử dụng.


Bài viết liên quan

Tính năng liên quan:SkillsFinanceDashboardPortfolio AnalysisFinancial Modeling

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.