<a id="sphx-glr-auto-examples-mean-risk-plot-1-maximum-sharpe-ratio-py"></a>

<a id="maximum-sharpe-ratio"></a>

# Maximum Sharpe Ratio

This tutorial uses the [`MeanRisk`](https://skfolio.org/generated/skfolio.optimization.MeanRisk.html.md#skfolio.optimization.MeanRisk) optimization to find the
maximum Sharpe Ratio portfolio.

<a id="data"></a>

## Data

We load the S&P 500 [dataset](https://skfolio.org/user_guide/datasets.html.md#datasets) 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.
Prices are transformed into linear returns (see [data preparation](https://skfolio.org/user_guide/data_preparation.html.md#data-preparation)) and split into a training set and a test set without shuffling to
avoid [data leakage](https://skfolio.org/user_guide/model_selection.html.md#data-leakage).

```Python
import numpy as np
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, MeanRisk, ObjectiveFunction
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)

print(X_train.head())
```

```none
                AAPL       AMD       BAC  ...       UNH       WMT       XOM
Date                                      ...
1990-01-03  0.007576 -0.030303  0.008045  ... -0.019355  0.000000 -0.010079
1990-01-04  0.003759 -0.015500 -0.021355  ... -0.009868 -0.005201 -0.009933
1990-01-05  0.003745 -0.031996 -0.021821  ... -0.043189 -0.010732 -0.005267
1990-01-08  0.003731  0.000000  0.005633  ... -0.020833  0.013630  0.015381
1990-01-09 -0.007435  0.016527  0.000000  ... -0.024823 -0.026619 -0.020114

[5 rows x 20 columns]
```

<a id="model"></a>

## Model

We create a Maximum Sharpe Ratio model and then fit it on the training set.
`portfolio_params` are parameters passed to the [`Portfolio`](https://skfolio.org/generated/skfolio.portfolio.Portfolio.html.md#skfolio.portfolio.Portfolio)
returned by the `predict` method. It can be
omitted, here we use it to give a name to our maximum Sharpe Ratio portfolio:

```Python
model = MeanRisk(
    risk_measure=RiskMeasure.STANDARD_DEVIATION,
    objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
    portfolio_params=dict(name="Max Sharpe"),
)
model.fit(X_train)
model.weights_
```

```none
array([9.43837536e-02, 1.23703226e-07, 4.32481917e-08, 1.20892854e-01,
       3.18418329e-02, 7.69682661e-08, 1.78420641e-04, 1.24117994e-01,
       8.50336295e-08, 2.77970034e-02, 1.31617984e-07, 1.49536746e-07,
       1.16362392e-01, 5.73881398e-02, 9.91607320e-07, 1.09506312e-01,
       8.64772579e-02, 1.84018669e-01, 1.34639296e-02, 3.35698407e-02])
```

To compare this model, we use an inverse volatility benchmark using
the [`InverseVolatility`](https://skfolio.org/generated/skfolio.optimization.InverseVolatility.html.md#skfolio.optimization.InverseVolatility) estimator:

```Python
benchmark = InverseVolatility(portfolio_params=dict(name="Inverse Vol"))
benchmark.fit(X_train)
benchmark.weights_
```

```none
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])
```

<a id="prediction"></a>

## Prediction

We predict the model and the benchmark on the test set:

```Python
pred_model = model.predict(X_test)
pred_bench = benchmark.predict(X_test)
```

The `predict` method returns a [`Portfolio`](https://skfolio.org/generated/skfolio.portfolio.Portfolio.html.md#skfolio.portfolio.Portfolio) object.

[`Portfolio`](https://skfolio.org/generated/skfolio.portfolio.Portfolio.html.md#skfolio.portfolio.Portfolio) is an array-container making it compatible
with `scikit-learn` tools: calling `np.asarray(pred_model)` gives the portfolio
returns (same as `pred_model.returns`):

```Python
np.asarray(pred_model)
```

```none
array([ 0.00805138,  0.01084096,  0.00199137, ...,  0.00932288,
        0.00152751, -0.01787269], shape=(2743,))
```

The [`Portfolio`](https://skfolio.org/generated/skfolio.portfolio.Portfolio.html.md#skfolio.portfolio.Portfolio) class contains a vast number of properties
and methods used for analysis.

For example:
<br/>
* pred_model.plot_cumulative_returns()
* pred_model.plot_composition()
* pred_model.summary()

```Python
print(pred_model.annualized_sharpe_ratio)
print(pred_bench.annualized_sharpe_ratio)
```

```none
1.0399724999465625
1.0036976120249752
```

<a id="analysis"></a>

## Analysis

For improved analysis, we load both predicted portfolios into a
[`Population`](https://skfolio.org/generated/skfolio.population.Population.html.md#skfolio.population.Population):

```Python
population = Population([pred_model, pred_bench])
```

The [`Population`](https://skfolio.org/generated/skfolio.population.Population.html.md#skfolio.population.Population) class also contains a
vast number of properties and methods used for analysis.
Let’s plot each portfolio composition:

```Python
population.plot_composition()
```

[plotly figure stripped from llms output]
<br />
<br />

#### NOTE
Every `plot` methods in `skfolio` returns a `plotly` figure.
To display a plotly figure, you may need to call `show()` and change the
default renderer: [https://plotly.com/python/renderers/](https://plotly.com/python/renderers/)

Let’s plot each portfolio cumulative returns:

```Python
fig = population.plot_cumulative_returns()
# show(fig) is only used for the documentation sticker.
show(fig)
```

<!doctype html>
[plotly figure stripped from llms output]

<br/>

Finally, let’s display the full summary of both strategies evaluated on the test
set:

```Python
population.summary()
```

<div class="output_subarea output_html rendered_html output_result">
<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Max Sharpe</th>
      <th>Inverse Vol</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Mean</th>
      <td>0.073%</td>
      <td>0.064%</td>
    </tr>
    <tr>
      <th>Annualized Mean</th>
      <td>18.43%</td>
      <td>16.06%</td>
    </tr>
    <tr>
      <th>Variance</th>
      <td>0.00012</td>
      <td>0.00010</td>
    </tr>
    <tr>
      <th>Annualized Variance</th>
      <td>3.14%</td>
      <td>2.56%</td>
    </tr>
    <tr>
      <th>Semi-Variance</th>
      <td>0.000063</td>
      <td>0.000053</td>
    </tr>
    <tr>
      <th>Annualized Semi-Variance</th>
      <td>1.58%</td>
      <td>1.33%</td>
    </tr>
    <tr>
      <th>Standard Deviation</th>
      <td>1.12%</td>
      <td>1.01%</td>
    </tr>
    <tr>
      <th>Annualized Standard Deviation</th>
      <td>17.72%</td>
      <td>16.00%</td>
    </tr>
    <tr>
      <th>Semi-Deviation</th>
      <td>0.79%</td>
      <td>0.73%</td>
    </tr>
    <tr>
      <th>Annualized Semi-Deviation</th>
      <td>12.58%</td>
      <td>11.54%</td>
    </tr>
    <tr>
      <th>Mean Absolute Deviation</th>
      <td>0.74%</td>
      <td>0.65%</td>
    </tr>
    <tr>
      <th>CVaR at 95%</th>
      <td>2.54%</td>
      <td>2.35%</td>
    </tr>
    <tr>
      <th>EVaR at 95%</th>
      <td>5.11%</td>
      <td>5.29%</td>
    </tr>
    <tr>
      <th>Worst Realization</th>
      <td>10.06%</td>
      <td>10.49%</td>
    </tr>
    <tr>
      <th>CDaR at 95%</th>
      <td>13.81%</td>
      <td>12.22%</td>
    </tr>
    <tr>
      <th>MAX Drawdown</th>
      <td>33.01%</td>
      <td>34.83%</td>
    </tr>
    <tr>
      <th>Average Drawdown</th>
      <td>3.00%</td>
      <td>2.34%</td>
    </tr>
    <tr>
      <th>EDaR at 95%</th>
      <td>19.53%</td>
      <td>20.05%</td>
    </tr>
    <tr>
      <th>First Lower Partial Moment</th>
      <td>0.37%</td>
      <td>0.32%</td>
    </tr>
    <tr>
      <th>Ulcer Index</th>
      <td>0.048</td>
      <td>0.040</td>
    </tr>
    <tr>
      <th>Gini Mean Difference</th>
      <td>1.11%</td>
      <td>0.98%</td>
    </tr>
    <tr>
      <th>Value at Risk at 95%</th>
      <td>1.54%</td>
      <td>1.45%</td>
    </tr>
    <tr>
      <th>Drawdown at Risk at 95%</th>
      <td>10.23%</td>
      <td>8.79%</td>
    </tr>
    <tr>
      <th>Entropic Risk Measure at 95%</th>
      <td>3.00</td>
      <td>3.00</td>
    </tr>
    <tr>
      <th>Fourth Central Moment</th>
      <td>0.000029%</td>
      <td>0.000022%</td>
    </tr>
    <tr>
      <th>Fourth Lower Partial Moment</th>
      <td>0.000011%</td>
      <td>0.000011%</td>
    </tr>
    <tr>
      <th>Skew</th>
      <td>29.59%</td>
      <td>-14.95%</td>
    </tr>
    <tr>
      <th>Kurtosis</th>
      <td>1890.11%</td>
      <td>2118.56%</td>
    </tr>
    <tr>
      <th>Sharpe Ratio</th>
      <td>0.066</td>
      <td>0.063</td>
    </tr>
    <tr>
      <th>Annualized Sharpe Ratio</th>
      <td>1.04</td>
      <td>1.00</td>
    </tr>
    <tr>
      <th>Sortino Ratio</th>
      <td>0.092</td>
      <td>0.088</td>
    </tr>
    <tr>
      <th>Annualized Sortino Ratio</th>
      <td>1.47</td>
      <td>1.39</td>
    </tr>
    <tr>
      <th>Mean Absolute Deviation Ratio</th>
      <td>0.099</td>
      <td>0.098</td>
    </tr>
    <tr>
      <th>First Lower Partial Moment Ratio</th>
      <td>0.20</td>
      <td>0.20</td>
    </tr>
    <tr>
      <th>Value at Risk Ratio at 95%</th>
      <td>0.047</td>
      <td>0.044</td>
    </tr>
    <tr>
      <th>CVaR Ratio at 95%</th>
      <td>0.029</td>
      <td>0.027</td>
    </tr>
    <tr>
      <th>Entropic Risk Measure Ratio at 95%</th>
      <td>0.00024</td>
      <td>0.00021</td>
    </tr>
    <tr>
      <th>EVaR Ratio at 95%</th>
      <td>0.014</td>
      <td>0.012</td>
    </tr>
    <tr>
      <th>Worst Realization Ratio</th>
      <td>0.0073</td>
      <td>0.0061</td>
    </tr>
    <tr>
      <th>Drawdown at Risk Ratio at 95%</th>
      <td>0.0071</td>
      <td>0.0073</td>
    </tr>
    <tr>
      <th>CDaR Ratio at 95%</th>
      <td>0.0053</td>
      <td>0.0052</td>
    </tr>
    <tr>
      <th>Calmar Ratio</th>
      <td>0.0022</td>
      <td>0.0018</td>
    </tr>
    <tr>
      <th>Average Drawdown Ratio</th>
      <td>0.024</td>
      <td>0.027</td>
    </tr>
    <tr>
      <th>EDaR Ratio at 95%</th>
      <td>0.0037</td>
      <td>0.0032</td>
    </tr>
    <tr>
      <th>Ulcer Index Ratio</th>
      <td>0.015</td>
      <td>0.016</td>
    </tr>
    <tr>
      <th>Gini Mean Difference Ratio</th>
      <td>0.066</td>
      <td>0.065</td>
    </tr>
    <tr>
      <th>Effective Number of Assets</th>
      <td>8.913458799107447</td>
      <td>18.460872007821077</td>
    </tr>
    <tr>
      <th>Assets Number</th>
      <td>20</td>
      <td>20</td>
    </tr>
  </tbody>
</table>
</div>
</div>
<br />
<br />

<a id="conclusion"></a>

## Conclusion

From the analysis on the test set, we see that the Maximum Sharpe Ratio portfolio
outperform the inverse-volatility benchmark for the mean and the ratio
measures including the Sharpe Ratio, and underperforms for the deviation and
shortfall measures.

#### SEE ALSO
This was a toy example, for more advanced concepts check the [user guide](https://skfolio.org/user_guide/index.html.md#user-guide) or the [other examples](https://skfolio.org/auto_examples/index.html.md#general-examples).

**Total running time of the script:** (0 minutes 4.091 seconds)

<a id="sphx-glr-download-auto-examples-mean-risk-plot-1-maximum-sharpe-ratio-py"></a>
