skfolio是Python中的最新投资组合优化库, 用来构建和优化投资组合。skfolio是基于scikit-learn构建的库,旨在简化投资组合优化流程,并提供与scikit-learn兼容的接口和功能。
文章背景 近年来,定量金融方法不断发展,将这些方法整合到一个统一的框架中变得尤为重要,尤其是在与机器学习模型无缝集成的情况下。skfolio应运而生,它专注于投资组合优化,并利用scikit-learn的优势,提供了高效的数据处理、模型选择、验证和超参数调优功能,同时降低了数据泄漏和过拟合的风险。
自2024年初发布以来,skfolio在GitHub上的关注度稳步上升,这表明其在量化金融领域的应用潜力。
1. 环境配置与数据准备 在开始投资组合优化之前,需要导入必要的库:
matplotlib
和 plotly
:用于数据可视化 import requestsimport pandas as pdimport
numpy as npfrom skfolio import PerfMeasure, RatioMeasure, RiskMeasure, Populationfrom skfolio.optimization import MeanRisk, ObjectiveFunctionfrom plotly.io import showimport seaborn as snsimport matplotlib.pyplot as plt
设置绘图风格和图形大小:
plt.style.use("seborm-v0.8-colorblind" ) plt.rcParams["figure.figsize" ] = (16 , 8 )
为了获取历史股票价格数据,使用Financial Modelling Prep的API,并下载FAANG公司(META、AAPL、AMZN、NFLX、GOOGL)的调整后收盘价数据,时间范围为2023年8月1日至今。
FAANG_TICKERS = ["META" , "AAPL" , "AMZN" , "NFLX" , "GOOGL" ] START_DATE = "2023-08-01" def get_adj_close_price (symbol, start_date) : hist_price_url = f"https://financialmodelingprep.com/api/v3/historical-price-full/{symbol} ?from={start_date} &apikey={FMP_API_KEY} " r_json = requests.get(hist_price_url).json() df = pd.DataFrame(r_json["historical" ]).set_index("date" ).sort_index() df.index = pd.to_datetime(df.index) return df[["adjClose" ]].rename(columns={"adjClose" : symbol}) price_df_list = [get_adj_close_price(ticker, START_DATE) for ticker in FAANG_TICKERS] prices_df = pd.concat(price_df_list, axis=1 )
生成的DataFrame如下:
date META AAPL AMZN NFLX GOOGL 2023-08-01 322.05 194.35 191.34 131.69 438.62 2023-08-02 313.67 128.21 429.70 128.23 128.30 ... ... ... ... ... ...
2024-08-16 527.42 226.05 170.23 177.59 674.07
绘制下载的时间序列数据:
为了进行投资组合优化,需要计算股票收益率:
returns_df = prices_to_returns(prices_df)
计算累计收益率并绘制:
cumulative_returns_df = (1 + returns_df).cumprod() - 1 cumulative_returns_df.plot(title="Cumulative Returns" )
从图中可以看出,在所考虑的时期内,META的累计收益率最高,超过了60%,其次是Netflix。
2. 投资组合优化 2.1 单个投资组合的构建 使用skfolio构建三种类型的投资组合:
最小化波动率的投资组合
model = MeanRisk( objective_function=ObjectiveFunction.MINIMIZE_RISK, risk_measure=RiskMeasure.VARIANCE, portfolio_params=dict(name="Min Variance" ) ) model.fit(returns_df) min_variance_pred = model.predict(returns_df)
objective_function
参数设置为 MINIMIZE_RISK
,表示最小化风险
risk_measure
参数设置为 VARIANCE
,表示使用方差作为风险度量 portfolio_params
参数用于设置投资组合的名称 使用scikit-learn的API将模型拟合到收益率数据,并进行预测。预测结果是一个 Portfolio
类的对象,包含了许多用于分析投资组合性能的实用工具。
查看投资组合权重:
model.weights# array([0.02359533, 0.49553118, 0.16225161, 0.14974249, 0.16887939])
最大化收益率的投资组合
model = MeanRisk( objective_function=ObjectiveFunction.MAXIMIZE_RETURN, portfolio_params=dict(name="Max Return" ) ) model.fit(returns_df) max_return_pred = model.predict(returns_df)
最大化夏普比率的投资组合
model = MeanRisk( objective_function=ObjectiveFunction.MAXIMIZE_RATIO, risk_measure=RiskMeasure.VARIANCE, portfolio_params=dict(name="Max Sharpe" ) ) model.fit(returns_df) max_sharpe_pred = model.predict(returns_df)
投资组合比较与分析
使用 Population
类可以方便地比较多个投资组合:
population = Population([min_variance_pred, max_return_pred, max_sharpe_pred]) population.plot_composition()
从图中可以看出,不同优化目标下的投资组合构成差异显著。例如,在最大化收益率的投资组合中,所有权重都分配给了META,这与累计收益率图中META的表现一致。
绘制投资组合的累计收益率:
population.plot_cumulative_returns()
最后,使用
summary
方法查看投资组合的详细性能指标:
population.summary()
指标 Min Variance Max Return Max Sharpe Mean 0.10% 0.21% 0.19% Annualized Mean 26.13% 53.88% 46.67% Variance 0.015% 0.054% 0.022% ... ... ... ... Sharpe Ratio 0.084 1.341 1.79 ... ... ... ...
Population
类提供了近50个不同的指标来评估投资组合的性能。
2.2 投资组合优化参数调整 MeanRisk
类提供了许多参数,可以根据需要进行调整:
在均值-方差优化中添加L2正则化,以减少微不足道的权重为零 为某些指标设置目标或阈值,例如最低收益率或最高波动率
3. 有效前沿的识别 有效前沿代表了在给定风险水平下提供最高预期收益率或给定收益率水平下提供最低风险的投资组合集合。
使用默认参数进行均值-方差优化,并指定要找到的投资组合数量:
model = MeanRisk(efficient_frontier_size=50 ) model.fit(returns_df) efficient_frontier = model.predict(returns_df)
绘制有效前沿:
fig = efficient_frontier.plot_measures( x=RiskMeasure.ANNUALIZED_VARIANCE, y=PerfMeasure.ANNUALIZED_MEAN, color_scale=RatioMeasure.ANNUALIZED_SHARPE_RATIO, hover_measures=[ RiskMeasure.MAX_DRAWDOWN, RatioMeasure.ANNUALIZED_SORTINO_RATIO, RiskMeasure.WORST_REALIZATION ] ) show(fig)
查看有效前沿上投资组合的构成:
efficient_frontier.plot_composition()
使用 summary
方法查看有效前沿上投资组合的性能指标:
efficient_frontier.summary()
为了便于分析,可以提取特定指标,例如年化夏普比率:
efficient_frontier(measure=RatioMeasure.ANNUALIZED_SHARPE_RATIO)
4. 总结与展望 本文介绍了如何使用skfolio进行投资组合优化:
使用均值-方差优化构建了三种类型的投资组合:最小化波动率、最大化收益率和最大化夏普比率。 使用 Population
类比较了不同投资组合的构成和性能。
5. 结论 skfolio是一个功能强大且易于使用的投资组合优化库,提供了丰富的功能和灵活的接口,可以满足不同投资者的需求。
通过本文的介绍,相信读者已经对如何使用skfolio进行投资组合优化有了更深入的了解。以下是一些建议:
从简单的均值-方差优化开始 ,熟悉skfolio的基本用法。尝试不同的估计方法和交叉验证方法 ,以提高投资组合模型的稳健性。探索更高级的功能 ,例如层次风险平价、投资组合约束和高级优化算法。skfolio仍在不断发展和完善中,未来将支持更多功能和算法。期待skfolio在量化金融领域发挥更大的作用,帮助投资者构建更有效的投资组合,实现更高的投资回报。