#### NOTE
[Go to the end](#sphx-glr-download-auto-examples-online-learning-plot-2-online-hyperparameter-tuning-py)
to download the full example code or to run this example in your browser via JupyterLite.

<a id="sphx-glr-auto-examples-online-learning-plot-2-online-hyperparameter-tuning-py"></a>

<a id="online-covariance-hyperparameter-tuning"></a>

# Online Covariance Hyperparameter Tuning

This tutorial shows how to tune covariance estimator hyperparameters in an online
setting using [`OnlineGridSearch`](https://skfolio.org/generated/skfolio.model_selection.OnlineGridSearch.html.md#skfolio.model_selection.OnlineGridSearch) and
[`OnlineRandomizedSearch`](https://skfolio.org/generated/skfolio.model_selection.OnlineRandomizedSearch.html.md#skfolio.model_selection.OnlineRandomizedSearch).

The online approach is equivalent to combining scikit-learn’s
`GridSearchCV`
(or `RandomizedSearchCV`) with
[`WalkForward`](https://skfolio.org/generated/skfolio.model_selection.WalkForward.html.md#skfolio.model_selection.WalkForward) using `expand_train=True`, but instead of
refitting every candidate from scratch at each split, it calls `partial_fit` to
incrementally update the estimator. This is significantly faster for estimators that
support this method.

<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 2010-01-04 up to 2022-12-28.

```Python
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.io import show
from scipy.stats import uniform

from skfolio.datasets import load_sp500_dataset
from skfolio.metrics import (
    diagonal_calibration_loss,
    make_scorer,
    portfolio_variance_qlike_loss,
)
from skfolio.model_selection import (
    OnlineGridSearch,
    OnlineRandomizedSearch,
    online_score,
)
from skfolio.moments import RegimeAdjustedEWCovariance
from skfolio.preprocessing import prices_to_returns

prices = load_sp500_dataset()
X = prices_to_returns(prices)
X = X["2010":]
```

<a id="build-scorers"></a>

## Build Scorers

We build scorers with [`make_scorer`](https://skfolio.org/generated/skfolio.metrics.make_scorer.html.md#skfolio.metrics.make_scorer).
We set `response_method=None` because a covariance estimator is a non-predictor
estimator (it does not implement `predict`), and `greater_is_better=False` because
both losses are minimized.

```Python
qlike_scorer = make_scorer(
    portfolio_variance_qlike_loss,
    greater_is_better=False,
    response_method=None,
)

calibration_scorer = make_scorer(
    diagonal_calibration_loss,
    greater_is_better=False,
    response_method=None,
)
```

<a id="onlinegridsearch"></a>

## OnlineGridSearch

We now tune [`RegimeAdjustedEWCovariance`](https://skfolio.org/generated/skfolio.moments.RegimeAdjustedEWCovariance.html.md#skfolio.moments.RegimeAdjustedEWCovariance) with
[`OnlineGridSearch`](https://skfolio.org/generated/skfolio.model_selection.OnlineGridSearch.html.md#skfolio.model_selection.OnlineGridSearch).

We search over `half_life`, `corr_half_life`, and `regime_half_life`.
`corr_half_life` controls the correlation smoothing separately from the
variance half-life, while `regime_half_life` controls how quickly the
regime adjustment adapts to market changes.

Each candidate is evaluated with a full online walk-forward pass. Here,
`warmup_size=252` uses the first year for initialization and `test_size=5`
evaluates windows of 5 consecutive daily observations (one trading week).

```Python
grid_search = OnlineGridSearch(
    estimator=RegimeAdjustedEWCovariance(),
    param_grid={
        "half_life": [20, 40, 60],
        "corr_half_life": [40, 80],
        "regime_half_life": [10, 20],
    },
    scoring=qlike_scorer,
    warmup_size=252,
    test_size=5,
    n_jobs=-1,
)
grid_search.fit(X)
```

[plotly figure stripped from llms output]<style>html[data-theme="dark"] div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}@media (prefers-color-scheme: dark){html:not([data-theme="light"]) div.output_subarea:has(.plotly-graph-div){background:#fff;border-radius:0.25rem;padding:0.5rem}}</style><script>if (!window.plotlySphinxGalleryResize) {window.plotlySphinxGalleryResize = true;window.addEventListener("load", function () {document.querySelectorAll(".plotly-graph-div").forEach(function (gd) { Plotly.Plots.resize(gd); });});}</script>

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

## Conclusion

This tutorial demonstrated how to tune online covariance estimator hyperparameters.

1. Build scorers with [`make_scorer`](https://skfolio.org/generated/skfolio.metrics.make_scorer.html.md#skfolio.metrics.make_scorer) and
   `response_method=None` for non-predictor estimators.
2. Use [`OnlineGridSearch`](https://skfolio.org/generated/skfolio.model_selection.OnlineGridSearch.html.md#skfolio.model_selection.OnlineGridSearch) for small,
   structured search spaces.
3. Use [`OnlineRandomizedSearch`](https://skfolio.org/generated/skfolio.model_selection.OnlineRandomizedSearch.html.md#skfolio.model_selection.OnlineRandomizedSearch) for larger
   continuous search spaces, specifying `refit` when scoring is multi-metric.
4. Evaluate and compare estimators numerically with
   [`online_score`](https://skfolio.org/generated/skfolio.model_selection.online_score.html.md#skfolio.model_selection.online_score).

In the [next tutorial](https://skfolio.org/auto_examples/online_learning/plot_3_online_portfolio_optimization_evaluation.html.md#sphx-glr-auto-examples-online-learning-plot-3-online-portfolio-optimization-evaluation-py),
we move from covariance tuning to end-to-end online portfolio optimization
evaluation with [`MeanRisk`](https://skfolio.org/generated/skfolio.optimization.MeanRisk.html.md#skfolio.optimization.MeanRisk).

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

<a id="sphx-glr-download-auto-examples-online-learning-plot-2-online-hyperparameter-tuning-py"></a>
[![Launch JupyterLite](auto_examples/online_learning/images/jupyterlite_badge_logo.svg)](../../lite/lab/index.html?path=auto_examples/online_learning/plot_2_online_hyperparameter_tuning.ipynb)

[`Download Jupyter notebook: plot_2_online_hyperparameter_tuning.ipynb`](https://skfolio.org/auto_examples/online_learning/_downloads/46a003a8206376844dc35c9301ade044/plot_2_online_hyperparameter_tuning.ipynb)

[`Download Python source code: plot_2_online_hyperparameter_tuning.py`](https://skfolio.org/auto_examples/online_learning/_downloads/545e602bc5dc84064d049df2e392c6e9/plot_2_online_hyperparameter_tuning.py)

[`Download zipped: plot_2_online_hyperparameter_tuning.zip`](https://skfolio.org/auto_examples/online_learning/_downloads/70f8cc734fc5d9e36c92c03ff918db9b/plot_2_online_hyperparameter_tuning.zip)

[Gallery generated by Sphinx-Gallery](https://sphinx-gallery.github.io)
