0Pricing
AI Agents · Pelajaran

Alat Agen untuk Analisis Portofolio

Penghitungan imbal hasil, rasio Sharpe, dan analisis penurunan melalui kode yang dijalankan agen.

Alat Agen untuk Analisis Portofolio adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Analisis Portofolio sebagai Alat Agen

Agen analisis keuangan memerlukan serangkaian alat kalkulasi yang dapat dipanggil oleh LLM: imbal hasil, metrik risiko, korelasi, dan saran penyeimbangan kembali. Setiap alat merupakan fungsi Python dengan tanda tangan yang jelas dan mengembalikan JSON terstruktur yang dapat dianalisis oleh agen.

Menghitung Imbal Hasil Persentase

Ini merupakan dasar analisis portofolio. pct_change() menghitung imbal hasil dari hari ke hari. Dari data tersebut, hitung imbal hasil kumulatif selama periode analisis.

import pandas as pd
import yfinance as yf

def calculate_returns(ticker: str, period: str = '1y') -> dict:
    hist = yf.Ticker(ticker).history(period=period)['Close']
    if hist.empty:
        return {'error': f'No data for {ticker}'}

    daily_returns = hist.pct_change().dropna()
    cumulative    = (1 + daily_returns).cumprod() - 1

    return {
        'ticker':            ticker,
        'period':            period,
        'total_return_pct':  round(float(cumulative.iloc[-1]) * 100, 2),
        'avg_daily_return':  round(float(daily_returns.mean()) * 100, 4),
        'best_day_pct':      round(float(daily_returns.max()) * 100, 2),
        'worst_day_pct':     round(float(daily_returns.min()) * 100, 2)
    }

Rasio Sharpe

Rasio Sharpe mengukur imbal hasil yang disesuaikan dengan risiko: seberapa besar imbal hasil berlebih yang diperoleh untuk setiap unit risiko (volatilitas). Nilai yang lebih tinggi lebih baik. Rasio Sharpe di atas 1,0 dianggap baik; di atas 2,0 dianggap sangat baik.

import numpy as np
import yfinance as yf

def sharpe_ratio(ticker: str, period: str = '1y',
                 risk_free_annual: float = 0.05) -> dict:
    hist = yf.Ticker(ticker).history(period=period)['Close']
    daily_returns = hist.pct_change().dropna()

    risk_free_daily = risk_free_annual / 252  # annualized to daily
    excess_returns  = daily_returns - risk_free_daily

    if daily_returns.std() == 0:
        return {'error': 'Zero volatility — cannot compute Sharpe ratio'}

    sharpe = float(excess_returns.mean() / excess_returns.std() * np.sqrt(252))
    return {
        'ticker': ticker,
        'sharpe_ratio': round(sharpe, 3),
        'interpretation': 'excellent' if sharpe > 2 else 'good' if sharpe > 1 else 'acceptable' if sharpe > 0 else 'poor'
    }

Penurunan Maksimum

Penurunan maksimum (MDD) adalah penurunan terbesar nilai portofolio dari titik puncak ke titik terendah. Ini menunjukkan kerugian terburuk yang akan dialami investor jika membeli di titik puncak dan menjual di titik terendah.

import yfinance as yf
import numpy as np

def max_drawdown(ticker: str, period: str = '1y') -> dict:
    hist = yf.Ticker(ticker).history(period=period)['Close']
    if hist.empty:
        return {'error': 'No data'}

    rolling_max = hist.cummax()
    drawdown    = (hist - rolling_max) / rolling_max
    mdd         = float(drawdown.min())
    mdd_date    = str(drawdown.idxmin().date())

    return {
        'ticker':           ticker,
        'max_drawdown_pct': round(mdd * 100, 2),
        'drawdown_date':    mdd_date,
        'interpretation':   'severe' if mdd < -0.30 else 'moderate' if mdd < -0.15 else 'mild'
    }

Matriks Korelasi

Matriks korelasi menunjukkan bagaimana aset bergerak secara bersamaan. Korelasi yang rendah atau negatif ant aset memberikan manfaat diversifikasi — jika satu aset turun, aset lainnya mungkin tidak ikut turun. Hal ini membantu menentukan aset dan mengambil keputusan penyeimbangan kembali.

import pandas as pd
import yfinance as yf

def correlation_matrix(tickers: list[str], period: str = '1y') -> dict:
    prices = yf.download(tickers, period=period)['Close']
    returns = prices.pct_change().dropna()
    corr = returns.corr().round(3)

    # Convert to JSON-serializable format
    result = {}
    for t1 in tickers:
        result[t1] = {}
        for t2 in tickers:
            if t1 in corr.columns and t2 in corr.index:
                result[t1][t2] = float(corr.loc[t2, t1])
    return {'correlation': result, 'period': period}

Volatilitas dan Beta

Volatilitas tahunan (simpangan baku yang diskalakan ke 252 hari perdagangan) mengukur risiko absolut. Beta mengukur risiko relatif terhadap pasar (biasanya S&P 500): beta > 1 berarti lebih volatil daripada pasar.

import numpy as np
import yfinance as yf

def volatility_and_beta(ticker: str, benchmark: str = 'SPY',
                        period: str = '1y') -> dict:
    data = yf.download([ticker, benchmark], period=period)['Close'].pct_change().dropna()

    if ticker not in data.columns or benchmark not in data.columns:
        return {'error': 'Insufficient data'}

    t_ret = data[ticker]
    b_ret = data[benchmark]

    vol_annualized = float(t_ret.std() * np.sqrt(252))

    cov = np.cov(t_ret, b_ret)
    beta = float(cov[0][1] / cov[1][1]) if cov[1][1] != 0 else 0.0

    return {
        'ticker':          ticker,
        'annual_vol_pct':  round(vol_annualized * 100, 2),
        'beta':            round(beta, 3),
        'market_sensitivity': 'high' if beta > 1.3 else 'market' if beta > 0.7 else 'low'
    }

Imbal Hasil dan Risiko Tingkat Portofolio

Analisis seluruh portofolio dengan menghitung imbal hasil dan volatilitas tertimbang. Portofolio dapat memiliki risiko yang lebih rendah daripada setiap aset yang dimilikinya karena diversifikasi.

import pandas as pd, numpy as np
import yfinance as yf

def portfolio_metrics(holdings: dict, period: str = '1y') -> dict:
    tickers  = list(holdings.keys())
    weights  = np.array(list(holdings.values()))
    weights /= weights.sum()  # normalize to 1.0

    prices  = yf.download(tickers, period=period)['Close'].pct_change().dropna()
    port_ret = (prices * weights).sum(axis=1)
    cov_matrix = prices.cov() * 252  # annualized

    port_return  = float(port_ret.mean() * 252)
    port_vol     = float(np.sqrt(weights @ cov_matrix.values @ weights))
    port_sharpe  = port_return / port_vol if port_vol > 0 else 0

    return {
        'annual_return_pct':  round(port_return * 100, 2),
        'annual_vol_pct':     round(port_vol * 100, 2),
        'sharpe_ratio':       round(port_sharpe, 3),
        'holdings':           {t: round(float(w), 3) for t, w in zip(tickers, weights)}
    }

Saran Penyeimbangan Kembali

Penyimpangan portofolio terjadi karena aset yang berbeda tumbuh dengan laju yang berbeda. Alat penyeimbangan kembali menghitung bobot saat ini dibandingkan dengan bobot target dan menyarankan transaksi untuk mengembalikan alokasi ke target.

def rebalancing_suggestion(current_values: dict, target_weights: dict) -> dict:
    total_value = sum(current_values.values())
    current_weights = {t: v / total_value for t, v in current_values.items()}
    trades = {}

    for ticker in target_weights:
        current_w = current_weights.get(ticker, 0)
        target_w  = target_weights[ticker]
        diff_w    = target_w - current_w
        diff_usd  = diff_w * total_value

        if abs(diff_w) > 0.01:  # only suggest if drift > 1%
            trades[ticker] = {
                'action':      'BUY' if diff_usd > 0 else 'SELL',
                'amount_usd':  round(abs(diff_usd), 2),
                'from_weight': round(current_w, 4),
                'to_weight':   round(target_w, 4)
            }
    return {'total_portfolio': round(total_value, 2), 'trades': trades}

if __name__ == '__main__':
    current = {'AAPL': 6000, 'BND': 2000, 'VTI': 2000}
    target = {'AAPL': 0.4, 'BND': 0.3, 'VTI': 0.3}
    result = rebalancing_suggestion(current, target)
    print('Total portfolio: $%s' % result['total_portfolio'])
    for ticker, trade in result['trades'].items():
        print(f"  {ticker}: {trade['action']} ${trade['amount_usd']} "
              f"(weight {trade['from_weight']} -> {trade['to_weight']})")

Mendaftarkan Alat Analisis untuk LLM

Daftarkan setiap fungsi analisis sebagai alat agen. LLM memanggilnya secara berurutan: pertama mengambil data, lalu menghitung metrik, kemudian membuat saran penyeimbangan kembali.

FINANCIAL_TOOLS = [
    {
        'type': 'function',
        'function': {
            'name': 'calculate_returns',
            'description': 'Calculate total and daily returns for a ticker.',
            'parameters': {'type': 'object',
                           'properties': {
                               'ticker': {'type': 'string'},
                               'period': {'type': 'string', 'default': '1y'}
                           }, 'required': ['ticker']}
        }
    },
    {
        'type': 'function',
        'function': {
            'name': 'sharpe_ratio',
            'description': 'Compute the annualized Sharpe ratio.',
            'parameters': {'type': 'object',
                           'properties': {
                               'ticker': {'type': 'string'},
                               'period': {'type': 'string', 'default': '1y'}
                           }, 'required': ['ticker']}
        }
    }
]

if __name__ == '__main__':
    print('Registered financial tools for the LLM:')
    for tool in FINANCIAL_TOOLS:
        fn = tool['function']
        print(f"  {fn['name']}: {fn['description']}")

Membuat Ringkasan Portofolio dalam Bahasa Sederhana

Setelah menghitung metrik, minta LLM menerjemahkan angka menjadi bahasa yang dapat ditindaklanjuti. Metrik merupakan masukan; keluaran akhir harus mudah dipahami oleh investor non-kuantitatif.

import openai, json

client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')

def portfolio_narrative(metrics: dict, holdings: dict) -> str:
    prompt = (
        f'Portfolio metrics:\n{json.dumps(metrics, indent=2)}\n\n'
        f'Holdings: {json.dumps(holdings)}\n\n'
        f'Write a 3-sentence plain-language portfolio assessment for a retail investor.\n'
        f'Include: overall performance, main risk, and one recommendation.'
    )
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return resp.choices[0].message.content

Menyimpan Metrik Hasil Perhitungan dalam Cache

Metrik yang dihitung dari data dasar yang sama akan selalu identik. Simpan metrik hasil perhitungan bersama data mentah untuk menghindari penghitungan ulang rasio Sharpe dan penurunan maksimum pada setiap giliran agen.

import time, hashlib, json

metrics_cache = {}

def cached_metric(func, *args, ttl: int = 3600):
    key = hashlib.md5(f'{func.__name__}:{args}'.encode()).hexdigest()
    entry = metrics_cache.get(key)
    if entry and time.time() - entry['ts'] < ttl:
        return entry['data']
    result = func(*args)
    metrics_cache[key] = {'data': result, 'ts': time.time()}
    return result

# Usage:
# sharpe = cached_metric(sharpe_ratio, 'AAPL', '1y')

if __name__ == '__main__':
    def slow_average(*nums):
        return sum(nums) / len(nums)

    r1 = cached_metric(slow_average, 1, 2, 3)
    r2 = cached_metric(slow_average, 1, 2, 3)
    print('First call result:', r1)
    print('Second call result (served from cache):', r2)
    print('Cache entries:', len(metrics_cache))

Apa arti rasio Sharpe di atas 2,0?

Rasio Sharpe merupakan metrik standar untuk membandingkan kinerja yang disesuaikan dengan risiko di antara portofolio dan aset individual.

Ringkasan Alat Analisis Portofolio

Perangkat agen keuangan mencakup: pct_change() untuk imbal hasil, rasio Sharpe untuk kinerja yang disesuaikan dengan risiko, penurunan maksimum untuk kerugian terburuk, matriks korelasi untuk diversifikasi, beta untuk sensitivitas terhadap pasar, dan saran penyeimbangan kembali untuk pemeliharaan portofolio.

Daftarkan masing-masing sebagai alat agen dan simpan hasil perhitungan dalam cache agar lebih efisien.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Alat Agen untuk Analisis Portofolio” gratis?

Ya — teks lengkap “Alat Agen untuk Analisis Portofolio” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Alat Agen untuk Analisis Portofolio”?

Penghitungan imbal hasil, rasio Sharpe, dan analisis penurunan melalui kode yang dijalankan agen. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Alat Agen untuk Analisis Portofolio” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?

Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Integrasi API Data Pasar
  2. Alat Agen untuk Analisis Portofolio
  3. Batas Pengaman Risiko dan Kepatuhan
  4. Pengujian Balik Keputusan Agen
← Kembali ke AI Agents