查看全集:💎Quantopia量化分析56讲
投资组合分析是量化金融领域的核心学科,旨在通过科学的方法评估和管理投资组合的风险与收益。在当今复杂多变的金融市场中,投资者面临着资产价格波动、宏观经济不确定性以及日益增长的市场数据量等挑战。传统的经验判断已不足以应对这些问题,因此,数据驱动的投资组合分析工具成为优化资产配置、评估绩效并有效控制风险的关键。本章旨在为读者提供一个系统化的学习路径,通过现代Python工具的应用,帮助您从零开始掌握投资组合分析的理论与实践。
通过本章的学习,您将能够实现以下目标:
在进行投资组合分析之前,我们需要搭建一个功能强大的Python环境,并获取可靠的金融市场数据。这一小节将详细介绍所需工具的安装和数据获取的完整流程。
为了完成本章的任务,您需要安装以下Python库。这些库各有其独特的功能,共同构成了投资组合分析的技术基础:
yfinance
:一个轻量级但功能强大的库,用于从Yahoo Finance下载金融数据。它支持股票、指数、ETF等多种资产类型的数据获取。pyfolio
:专为投资组合分析设计的开源工具,提供绩效评估、可视化图表和风险分析功能,是量化投资者的得力助手。empyrical
:专注于风险和绩效指标计算的库,支持夏普比率、最大回撤、贝塔等常用指标的高效计算。matplotlib
:Python中最流行的绘图库,用于创建各种静态和动态图表,帮助我们直观展示分析结果。安装这些库的命令如下,在终端或命令行中运行:
bash
pip install yfinance pyfolio empyrical matplotlib
安装注意事项:
pip install --upgrade pip
更新pip后重试。以下是一个通过yfinance
具体的示例,展示如何获取标普500指数(SPY)以及个股(如苹果AAPL和微软MSFT)的收盘价数据,并计算日收益率:
import yfinance as yf
import pandas as pd
# 获取标普500和个股数据
start = '2014-01-01'
end = '2015-01-01'
benchmark = yf.download('SPY', start=start, end=end)['Close']
assets = yf.download(['AAPL', 'MSFT'], start=start, end=end)['Close']
# 计算收益率
benchmark_rets = benchmark.pct_change().dropna()
portfolio_rets = assets.pct_change().mean(axis=1).dropna() # 假设等权投资
数据检查与预处理:
yfinance
返回的数据可能包含多级列索引(如Close, Open等),使用['Close']可以简化结构。datetime
格式。如果不是,可通过以下代码修正:assets.index = pd.to_datetime(assets.index)
print(assets.head())
进行检查。投资组合的绩效评估依赖于一系列关键指标,这些指标帮助我们量化收益与风险的关系。以下是对三个核心指标的详细解析,包括定义、公式、代码实现和解读。
夏普比率是由诺贝尔经济学奖得主威廉·夏普提出的经典指标,用于衡量投资组合在承担单位风险时获得的超额收益。它是风险调整后收益的黄金标准。
公式:
from empyrical import sharpe_ratio
# 计算夏普比率(假设无风险利率为0)
sharpe = sharpe_ratio(portfolio_rets)
print(f"夏普比率: {sharpe:.2f}")
解读:
最大回撤衡量投资组合从历史最高点到随后最低点所经历的最大亏损幅度,是评估极端风险的重要指标。它直接反映了投资者可能面临的最坏情况。
公式:
最大回撤通常通过计算累积收益率曲线的高点与低点之差来确定:
代码实现:
from empyrical import max_drawdown
dd = max_drawdown(portfolio_rets)
print(f"最大回撤: {abs(dd)*100:.1f}%")
解读:
市场贝塔衡量投资组合相对于市场(如标普500)的系统性风险,反映其对市场整体波动的敏感度。它是资本资产定价模型(CAPM)中的核心参数。
公式:
其中:
表示贝塔系数
表示投资组合收益率与市场收益率的协方差
表示市场收益率的方差
表示投资组合收益率
表示市场收益率
from empyrical import beta
market_beta = beta(portfolio_rets, benchmark_rets)
print(f"市场贝塔: {market_beta:.2f}")
解读:
任务:计算投资组合的年化波动率,并以百分比形式输出,作为风险的直观度量。
代码实现:
# 提示:使用empyrical.annual_volatility()
可视化分析是将复杂数据转化为直观洞见的关键步骤。以下介绍三种常用的可视化方法,帮助您深入理解投资组合的表现和风险。
通过绘制投资组合与基准(如标普500)的累积收益率曲线,评估其相对表现和长期趋势。
代码实现:
import pyfolio as pf
import matplotlib.pyplot as plt
# 创建双图布局
fig, ax = plt.subplots(2, 1, figsize=(10, 8))
# 绘制滚动累积收益率
pf.plotting.plot_rolling_returns(portfolio_rets, benchmark_rets, ax=ax[0])
ax[0].set_title("滚动累积收益率对比")
# 绘制日收益率
pf.plotting.plot_returns(portfolio_rets, ax=ax[1])
ax[1].set_title("日收益率")
plt.tight_layout()
plt.show()
说明:
通过热力图展示投资组合的月度收益分布,快速识别高收益或亏损月份,以及潜在的季节性模式。
pf.plot_monthly_returns_heatmap(portfolio_rets)
plt.title("月度收益热力图")
plt.show()
说明:
分析投资组合的滚动贝塔和滚动夏普比率,观察其风险和绩效随时间的变化:
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
# 绘制滚动贝塔
pf.plot_rolling_beta(portfolio_rets, benchmark_rets, ax=axes[0])
axes[0].set_title("滚动贝塔")
# 绘制滚动夏普比率
pf.plot_rolling_sharpe(portfolio_rets, ax=axes[1])
axes[1].set_title("滚动夏普比率")
plt.tight_layout()
plt.show()
说明:
在掌握基本指标和可视化后,我们进一步探索高级风险分析技术,以更全面地评估投资组合。
识别投资组合历史上主要的回撤周期,分析其在不同市场环境下的损失特征:
pf.plot_drawdown_periods(portfolio_rets)
plt.title("回撤周期分析")
plt.show()
说明:
基于Fama-French三因子模型,分析投资组合对市场风险、规模因子(SMB)和价值因子(HML)的暴露,揭示其风格特征:
pf.plot_rolling_fama_french(portfolio_rets)
plt.title("Fama-French 三因子滚动暴露")
plt.show()
说明:
指标 | 适用场景 | 优点 | 局限性 |
---|---|---|---|
夏普比率 | 收益近似正态分布 | 简单易用,广泛接受 | 对尾部风险(如黑天鹅事件)不敏感 |
索提诺比率 | 关注下行风险的投资者 | 聚焦损失,适合风险厌恶者 | 需定义最低可接受回报,计算复杂 |
最大回撤 | 评估最坏情况下的损失 | 直观反映极端风险 | 只关注单一事件,忽略频率和恢复时间 |
选择建议:
通过一个模拟案例,我们将理论应用于实践,强化您的分析能力:
案例数据集
生成一个模拟的投资组合收益率数据:
# 生成模拟数据
import numpy as np
dates = pd.date_range('2020-01-01', periods=500)
returns = pd.Series(np.random.normal(0.0005, 0.01, 500), index=dates)
诊断任务
from empyrical import sharpe_ratio
sharpe = sharpe_ratio(returns, annualization=252)
print(f"年化夏普比率: {sharpe:.2f}")
csi300 = yf.download('000300.SS', start='2020-01-01', end='2021-05-01')['Close'].pct_change().dropna()
csi300 = csi300.reindex(returns.index).dropna()
returns_aligned = returns.reindex(csi300.index).dropna()
pf.plot_rolling_beta(returns_aligned, csi300)
plt.title("滚动贝塔(对比沪深300)")
plt.show()
pf.plot_drawdown_periods(returns)
plt.title("最大回撤周期")
plt.show()
# 多资产批量下载
data = yf.download(['AAPL', 'MSFT', 'TSLA'],
start='2020-01-01',
end='2023-01-01',
group_by='ticker')
# 数据重整
aapl = data['AAPL']['Close'].rename('AAPL')
msft = data['MSFT']['Close'].rename('MSFT')
portfolio = pd.concat([aapl, msft], axis=1)
通过本教程,您已掌握使用现代Python工具进行专业级组合分析的核心方法。建议在实践中逐步增加: