Strumenti dell’agente per l’analisi dei portafogli
Calcolo dei rendimenti, indice di Sharpe e analisi del drawdown tramite codice eseguito dall’agente.
Strumenti dell’agente per l’analisi dei portafogli è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.
L'analisi del portafoglio come strumento dell'agente
Gli agenti di analisi finanziaria necessitano di una serie di strumenti di calcolo che l'LLM possa chiamare: rendimenti, metriche di rischio, correlazione e suggerimenti di ribilanciamento. Ogni strumento è una funzione Python con una firma chiara e restituisce JSON strutturato, che l'agente può utilizzare per il ragionamento.
Calcolare i rendimenti percentuali
È il fondamento dell'analisi del portafoglio. pct_change() calcola i rendimenti giornalieri. A partire da questi, calcoli il rendimento cumulativo nel periodo di analisi.
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)
}Indice di Sharpe
L'indice di Sharpe misura il rendimento corretto per il rischio: quanto rendimento in eccesso si ottiene per unità di rischio (volatilità). Più è alto, meglio è. Un indice di Sharpe superiore a 1.0 è considerato buono; oltre 2.0 è eccellente.
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'
}Massimo drawdown
Il massimo drawdown (MDD) è il più grande calo dal picco al minimo nel valore di un portafoglio. Rappresenta la perdita peggiore che un investitore avrebbe subito acquistando al picco e vendendo al minimo.
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'
}Matrice di correlazione
Una matrice di correlazione mostra come si muovono insieme gli asset. Una correlazione bassa o negativa tra gli asset indica un vantaggio di diversificazione: se uno scende, l'altro potrebbe non farlo. Questo orienta la selezione degli asset e le decisioni di ribilanciamento.
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}Volatilità e beta
La volatilità annualizzata (la deviazione standard rapportata a 252 giorni di contrattazione) misura il rischio assoluto. Il beta misura il rischio relativo al mercato, generalmente l'S&P 500: beta > 1 significa una volatilità superiore a quella del mercato.
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'
}Rendimento e rischio a livello di portafoglio
Analizzi un intero portafoglio calcolando i rendimenti ponderati e la volatilità. Grazie alla diversificazione, il portafoglio può presentare un rischio inferiore a quello di ogni singola posizione.
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)}
}Suggerimento di ribilanciamento
Il disallineamento del portafoglio si verifica quando asset diversi crescono a ritmi diversi. Lo strumento di ribilanciamento calcola i pesi attuali e quelli obiettivo e suggerisce le operazioni necessarie per ripristinare l'allocazione obiettivo.
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']})")
Registrare gli strumenti di analisi per l'LLM
Registri ogni funzione di analisi come strumento dell'agente. L'LLM li chiama in sequenza: prima recupera i dati, poi calcola le metriche e infine genera il suggerimento di ribilanciamento.
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']}")
Generare un riepilogo del portafoglio in linguaggio semplice
Dopo aver calcolato le metriche, chieda all'LLM di tradurre i numeri in indicazioni operative. Le metriche sono gli input; l'output finale deve essere comprensibile a un investitore che non sia un analista quantitativo.
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.contentMemorizzare nella cache le metriche calcolate
Le metriche calcolate a partire dagli stessi dati sottostanti saranno identiche. Memorizzi nella cache le metriche calcolate insieme ai dati grezzi, per evitare di ricalcolare gli indici di Sharpe e i drawdown a ogni turno dell'agente.
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))
Che cosa indica un indice di Sharpe superiore a 2.0?
L'indice di Sharpe è una metrica standard per confrontare la performance corretta per il rischio tra portafogli e singoli asset.
Riepilogo degli strumenti di analisi del portafoglio
Il kit di strumenti di un agente finanziario include: pct_change() per i rendimenti, indice di Sharpe per la performance corretta per il rischio, massimo drawdown per la perdita peggiore, matrice di correlazione per la diversificazione, beta per la sensibilità al mercato e suggerimenti di ribilanciamento per la gestione del portafoglio.
Registri ciascuno di questi strumenti come strumento dell'agente e memorizzi nella cache i risultati calcolati per una maggiore efficienza.
Domande Frequenti
La lezione «Strumenti dell’agente per l’analisi dei portafogli» è gratuita?
Sì — il testo completo di «Strumenti dell’agente per l’analisi dei portafogli» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.
Cosa imparerò in «Strumenti dell’agente per l’analisi dei portafogli»?
Calcolo dei rendimenti, indice di Sharpe e analisi del drawdown tramite codice eseguito dall’agente. Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Agents?
Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Strumenti dell’agente per l’analisi dei portafogli»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Agents?
Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Integrazione delle API per i dati di mercato
- Strumenti dell’agente per l’analisi dei portafogli
- Limiti di sicurezza per rischio e conformità
- Backtesting delle decisioni dell’agente