投资组合分析智能体工具
通过智能体执行的代码计算收益、夏普比率并分析回撤
投资组合分析智能体工具 是 CoddyKit 上的免费 AI Agents 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Agents 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Agents 课程共包含 4 节课。
将投资组合分析作为智能体工具
金融分析智能体需要一套可供 LLM 调用的计算工具,包括收益率、风险指标、相关性和再平衡建议。每个工具都是一个具有清晰签名的 Python 函数,并返回智能体可以进行推理的结构化 JSON。
计算百分比收益率
这是投资组合分析的基础。pct_change()计算每日收益率。根据这些收益率,可以计算分析期间的累计收益率。
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)
}夏普比率
夏普比率衡量风险调整后收益:您每承担一个单位的风险(波动率)可以获得多少超额收益。数值越高越好。夏普比率高于 1.0 通常被认为表现良好,高于 2.0 则属于优秀。
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'
}最大回撤
最大回撤(MDD)是投资组合价值从峰值到谷值的最大跌幅。它表示投资者如果在峰值买入、在谷值卖出,所经历的最坏损失。
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'
}相关性矩阵
相关性矩阵展示资产如何共同变动。资产之间较低或为负的相关性意味着具有分散化收益——如果一项资产下跌,另一项资产可能不会下跌。这有助于指导资产选择和再平衡决策。
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}波动率与贝塔
年化波动率(按 252 个交易日进行缩放的标准差)衡量绝对风险。贝塔衡量相对于市场的风险(通常以标普 500 指数为基准):贝塔 > 1 表示波动性高于市场。
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'
}投资组合层面的收益与风险
通过计算加权收益率和波动率来分析整个投资组合。由于分散化作用,投资组合的风险可能低于其中任何一项单独持仓的风险。
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)}
}再平衡建议
由于不同资产的增长速度不同,投资组合会逐渐偏离原定配置。再平衡工具会计算当前权重与目标权重,并建议通过交易恢复目标配置。
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']})")
为 LLM 注册分析工具
将每个分析函数注册为智能体工具。LLM 按顺序调用它们:先获取数据,然后计算指标,最后生成再平衡建议。
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']}")
生成易懂的投资组合摘要
计算指标后,让 LLM 将数字转化为可执行的语言。指标只是输入;最终输出应当让非量化投资者也能读懂。
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缓存计算出的指标
根据相同底层数据计算出的指标会完全一致。请将计算出的指标与原始数据一起缓存,避免在智能体每次运行时都重新计算夏普比率和回撤。
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))
夏普比率高于 2.0 表示什么
夏普比率是比较不同投资组合和单项资产风险调整后表现的标准指标。
投资组合分析工具回顾
金融智能体的工具包包括:用于计算收益率的 pct_change()、用于衡量风险调整后表现的夏普比率、用于衡量最坏损失的最大回撤、用于评估分散化程度的相关性矩阵、用于衡量市场敏感度的贝塔,以及用于维护投资组合的再平衡建议。
请将每项功能注册为智能体工具,并缓存计算结果以提高效率。
用 AI 导师学习 AI Agents — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 60
- 课程
- 239
常见问题解答
「投资组合分析智能体工具」课时是免费的吗?
是的 — 「投资组合分析智能体工具」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Agents 课程的其余内容,请升级到 CoddyKit PRO。 AI Agents 课程共包含 4 节课。
「投资组合分析智能体工具」这节课中我会学到什么?
通过智能体执行的代码计算收益、夏普比率并分析回撤 你通过在浏览器中直接运行的动手代码来练习 AI Agents,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Agents 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Agents 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「投资组合分析智能体工具」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Agents 课中编写并运行代码吗?
能。每节 AI Agents 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 市场数据 API 集成
- 投资组合分析智能体工具
- 风险与合规护栏
- 回测智能体决策