Note
Go to the end to download the full example code. or to run this example in your browser via JupyterLite or Binder
Risk Budgeting - CVaR#
This tutorial uses the RiskBudgeting
optimization to
build a risk budgeting portfolio by specifying a risk budget on each asset with CVaR as
the risk measure.
Data#
We load the S&P 500 dataset composed of the daily prices of 20 assets from the S&P 500 Index composition starting from 1990-01-02 up to 2022-12-28:
from plotly.io import show
from sklearn.model_selection import train_test_split
from skfolio import Population, RiskMeasure
from skfolio.datasets import load_sp500_dataset
from skfolio.optimization import InverseVolatility, RiskBudgeting
from skfolio.preprocessing import prices_to_returns
prices = load_sp500_dataset()
X = prices_to_returns(prices)
X_train, X_test = train_test_split(X, test_size=0.33, shuffle=False)
Risk Budget#
We chose the following risk budget: 1.5 on Apples, 0.2 on General Electric and JPMorgan and 1.0 on the remaining assets:
risk_budget = {asset_name: 1 for asset_name in X.columns}
risk_budget["AAPL"] = 1.5
risk_budget["GE"] = 0.2
risk_budget["JPM"] = 0.2
Model#
We create the risk budgeting model and then fit it on the training set:
model = RiskBudgeting(
risk_measure=RiskMeasure.CVAR,
risk_budget=risk_budget,
portfolio_params=dict(name="Risk Budgeting - CVaR"),
)
model.fit(X_train)
model.weights_
array([0.06173016, 0.03257461, 0.03336015, 0.03994768, 0.06348968,
0.0093012 , 0.04579241, 0.06880861, 0.00765335, 0.06700177,
0.05537228, 0.05430773, 0.04828249, 0.07033698, 0.05371274,
0.06892752, 0.04230882, 0.04897392, 0.06251756, 0.06560031])
To compare this model, we use an inverse volatility benchmark using
the InverseVolatility
estimator:
bench = InverseVolatility(portfolio_params=dict(name="Inverse Vol"))
bench.fit(X_train)
bench.weights_
array([0.03306735, 0.02548697, 0.03551377, 0.0296872 , 0.06358463,
0.05434705, 0.04742354, 0.07049715, 0.03882539, 0.06697905,
0.05570808, 0.05576851, 0.04723274, 0.06351213, 0.05581397,
0.0676481 , 0.02564642, 0.03970752, 0.05744543, 0.06610498])
Risk Contribution Analysis#
Let’s analyze the risk contribution of both models on the training set. As expected, the risk budgeting model has 50% more CVaR contribution to Apple and 80% less to General Electric and JPMorgan compared to the other assets:
ptf_model_train = model.predict(X_train)
fig = ptf_model_train.plot_contribution(measure=RiskMeasure.CVAR)
show(fig)
And the inverse volatility model has different CVaR contribution for each asset:
ptf_bench_train = bench.predict(X_train)
ptf_bench_train.plot_contribution(measure=RiskMeasure.CVAR)
Prediction#
We predict the model and the benchmark on the test set:
ptf_model_test = model.predict(X_test)
ptf_bench_test = bench.predict(X_test)
Analysis#
For improved analysis, it’s possible to load both predicted portfolios into a
Population
:
population = Population([ptf_model_test, ptf_bench_test])
Let’s plot each portfolio composition:
population.plot_composition()
Let’s plot each portfolio cumulative returns:
fig = population.plot_cumulative_returns()
show(fig)
Finally, we print a full summary of both strategies evaluated on the test set:
population.summary()
Total running time of the script: (0 minutes 1.922 seconds)