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

<div class="output_subarea output_html rendered_html output_result">
<style>.sk-global {
  /\* Definition of color scheme common for light and dark mode \*/
  --sklearn-color-text: #000;
  --sklearn-color-text-muted: #666;
  --sklearn-color-line: gray;
  /\* Definition of color scheme for unfitted estimators \*/
  --sklearn-color-unfitted-level-0: #fff5e6;
  --sklearn-color-unfitted-level-1: #f6e4d2;
  --sklearn-color-unfitted-level-2: #ffe0b3;
  --sklearn-color-unfitted-level-3: chocolate;
  /\* Definition of color scheme for fitted estimators \*/
  --sklearn-color-fitted-level-0: #f0f8ff;
  --sklearn-color-fitted-level-1: #d4ebff;
  --sklearn-color-fitted-level-2: #b3dbfd;
  --sklearn-color-fitted-level-3: cornflowerblue;
}

.sk-global.light {
  /\* Specific color for light theme \*/
  --sklearn-color-text-on-default-background: black;
  --sklearn-color-background: white;
  --sklearn-color-border-box: black;
  --sklearn-color-icon: #696969;
}

.sk-global.dark {
  --sklearn-color-text-on-default-background: white;
  --sklearn-color-background: #111;
  --sklearn-color-border-box: white;
  --sklearn-color-icon: #878787;
}

.sk-global {
  color: var(--sklearn-color-text);
}

.sk-global pre {
  padding: 0;
}

.sk-global input.sk-hidden--visually {
  border: 0;
  clip-path: inset(100%);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}

.sk-global div.sk-dashed-wrapped {
  border: 1px dashed var(--sklearn-color-line);
  margin: 0 0.4em 0.5em 0.4em;
  box-sizing: border-box;
  padding-bottom: 0.4em;
  background-color: var(--sklearn-color-background);
}

.sk-global div.sk-container {
  /\* jupyter's \`normalize.less\` sets \`[hidden] { display: none; }\`
     but bootstrap.min.css set \`[hidden] { display: none !important; }\`
     so we also need the \`!important\` here to be able to override the
     default hidden behavior on the sphinx rendered scikit-learn.org.
     See: https://github.com/scikit-learn/scikit-learn/issues/21755 \*/
  display: inline-block !important;
  position: relative;
}

.sk-global div.sk-text-repr-fallback {
  display: none;
}

div.sk-parallel-item,
div.sk-serial,
div.sk-item {
  /\* draw centered vertical line to link estimators \*/
  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));
  background-size: 2px 100%;
  background-repeat: no-repeat;
  background-position: center center;
}

/\* Parallel-specific style estimator block \*/

.sk-global div.sk-parallel-item::after {
  content: "";
  width: 100%;
  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);
  flex-grow: 1;
}

.sk-global div.sk-parallel {
  display: flex;
  align-items: stretch;
  justify-content: center;
  background-color: var(--sklearn-color-background);
  position: relative;
}

.sk-global div.sk-parallel-item {
  display: flex;
  flex-direction: column;
}

.sk-global div.sk-parallel-item:first-child::after {
  align-self: flex-end;
  width: 50%;
}

.sk-global div.sk-parallel-item:last-child::after {
  align-self: flex-start;
  width: 50%;
}

.sk-global div.sk-parallel-item:only-child::after {
  width: 0;
}

/\* Serial-specific style estimator block \*/

.sk-global div.sk-serial {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: var(--sklearn-color-background);
  padding-right: 1em;
  padding-left: 1em;
}

/\* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is
clickable and can be expanded/collapsed.
- Pipeline and ColumnTransformer use this feature and define the default style
- Estimators will overwrite some part of the style using the \`sk-estimator\` class
\*/

/\* Pipeline and ColumnTransformer style (default) \*/

.sk-global div.sk-toggleable {
  /\* Default theme specific background. It is overwritten whether we have a
  specific estimator or a Pipeline/ColumnTransformer \*/
  background-color: var(--sklearn-color-background);
}

/\* Toggleable label \*/
.sk-global label.sk-toggleable_\_label {
  cursor: pointer;
  display: flex;
  width: 100%;
  margin-bottom: 0;
  padding: 0.5em;
  box-sizing: border-box;
  text-align: center;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
}

.sk-global label.sk-toggleable_\_label .caption {
  font-size: 0.6rem;
  font-weight: lighter;
  color: var(--sklearn-color-text-muted);
}

.sk-global label.sk-toggleable_\_label-arrow:before {
  /\* Arrow on the left of the label \*/
  content: "▸";
  float: left;
  margin-right: 0.25em;
  color: var(--sklearn-color-icon);
}

.sk-global label.sk-toggleable_\_label-arrow:hover:before {
  color: var(--sklearn-color-text);
}

/\* Toggleable content - dropdown \*/

.sk-global div.sk-toggleable_\_content {
  display: none;
  text-align: left;
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-0);
}

.sk-global div.sk-toggleable_\_content.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
}

.sk-global div.sk-toggleable_\_content pre {
  margin: 0.2em;
  border-radius: 0.25em;
  color: var(--sklearn-color-text);
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-0);
}

.sk-global div.sk-toggleable_\_content.fitted pre {
  /\* unfitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
}

.sk-global input.sk-toggleable_\_control:checked~div.sk-toggleable_\_content {
  /\* Expand drop-down \*/
  display: block;
  width: 100%;
  overflow: visible;
}

.sk-global input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label-arrow:before {
  content: "▾";
}

/\* Pipeline/ColumnTransformer-specific style \*/

.sk-global div.sk-label input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-unfitted-level-2);
}

.sk-global div.sk-label.fitted input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  background-color: var(--sklearn-color-fitted-level-2);
}

/\* Estimator-specific style \*/

/\* Colorize estimator box \*/
.sk-global div.sk-estimator input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-2);
}

.sk-global div.sk-estimator.fitted input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-2);
}

.sk-global div.sk-label label.sk-toggleable_\_label,
.sk-global div.sk-label label {
  /\* The background is the default theme color \*/
  color: var(--sklearn-color-text-on-default-background);
}

/\* On hover, darken the color of the background \*/
.sk-global div.sk-label:hover label.sk-toggleable_\_label {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-unfitted-level-2);
}

/\* Label box, darken color on hover, fitted \*/
.sk-global div.sk-label.fitted:hover label.sk-toggleable_\_label.fitted {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-fitted-level-2);
}

/\* Estimator label \*/

.sk-global div.sk-label label {
  font-family: monospace;
  font-weight: bold;
  line-height: 1.2em;
}

.sk-global div.sk-label-container {
  text-align: center;
}

/\* Estimator-specific \*/
.sk-global div.sk-estimator {
  font-family: monospace;
  border: 1px dotted var(--sklearn-color-border-box);
  border-radius: 0.25em;
  box-sizing: border-box;
  margin-bottom: 0.5em;
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-0);
}

.sk-global div.sk-estimator.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
}

/\* on hover \*/
.sk-global div.sk-estimator:hover {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-2);
}

.sk-global div.sk-estimator.fitted:hover {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-2);
}

/\* Specification for estimator info (e.g. "i" and "?") \*/

/\* Common style for "i" and "?" \*/

.sk-estimator-doc-link,
a:link.sk-estimator-doc-link,
a:visited.sk-estimator-doc-link {
  float: right;
  font-size: smaller;
  line-height: 1em;
  font-family: monospace;
  background-color: var(--sklearn-color-unfitted-level-0);
  border-radius: 1em;
  height: 1em;
  width: 1em;
  text-decoration: none !important;
  margin-left: 0.5em;
  text-align: center;
  /\* unfitted \*/
  border: var(--sklearn-color-unfitted-level-3) 1pt solid;
  color: var(--sklearn-color-unfitted-level-3);
}

.sk-estimator-doc-link.fitted,
a:link.sk-estimator-doc-link.fitted,
a:visited.sk-estimator-doc-link.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
  border: var(--sklearn-color-fitted-level-3) 1pt solid;
  color: var(--sklearn-color-fitted-level-3);
}

/\* On hover \*/
div.sk-estimator:hover .sk-estimator-doc-link:hover,
.sk-estimator-doc-link:hover,
div.sk-label-container:hover .sk-estimator-doc-link:hover,
.sk-estimator-doc-link:hover {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-3);
  border: var(--sklearn-color-fitted-level-0) 1pt solid;
  color: var(--sklearn-color-unfitted-level-0);
  text-decoration: none;
}

div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,
.sk-estimator-doc-link.fitted:hover,
div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,
.sk-estimator-doc-link.fitted:hover {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-3);
  border: var(--sklearn-color-fitted-level-0) 1pt solid;
  color: var(--sklearn-color-fitted-level-0);
  text-decoration: none;
}

/\* Span, style for the box shown on hovering the info icon \*/
.sk-estimator-doc-link span {
  display: none;
  z-index: 9999;
  position: relative;
  font-weight: normal;
  right: .2ex;
  padding: .5ex;
  margin: .5ex;
  width: min-content;
  min-width: 20ex;
  max-width: 50ex;
  color: var(--sklearn-color-text);
  box-shadow: 2pt 2pt 4pt #999;
  /\* unfitted \*/
  background: var(--sklearn-color-unfitted-level-0);
  border: .5pt solid var(--sklearn-color-unfitted-level-3);
}

.sk-estimator-doc-link.fitted span {
  /\* fitted \*/
  background: var(--sklearn-color-fitted-level-0);
  border: var(--sklearn-color-fitted-level-3);
}

.sk-estimator-doc-link:hover span {
  display: block;
}

/\* "?"-specific style due to the \`<a>\` HTML tag \*/

.sk-global a.estimator_doc_link {
  float: right;
  font-size: 1rem;
  line-height: 1em;
  font-family: monospace;
  background-color: var(--sklearn-color-unfitted-level-0);
  border-radius: 1rem;
  height: 1rem;
  width: 1rem;
  text-decoration: none;
  /\* unfitted \*/
  color: var(--sklearn-color-unfitted-level-1);
  border: var(--sklearn-color-unfitted-level-1) 1pt solid;
}

.sk-global a.estimator_doc_link.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
  border: var(--sklearn-color-fitted-level-1) 1pt solid;
  color: var(--sklearn-color-fitted-level-1);
}

/\* On hover \*/
.sk-global a.estimator_doc_link:hover {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-3);
  color: var(--sklearn-color-background);
  text-decoration: none;
}

.sk-global a.estimator_doc_link.fitted:hover {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-3);
}

.sk-top-container.sk-global {
  /\* pydata-sphinx-theme hides overflow, so scrolling is disabled.
   We need to set it to !important and add tabindex="0" in the HTML
   to allow keyboard-only users to navigate the display. \*/
  overflow-x: scroll !important;
  max-width: 100%;
}

.estimator-table {
    font-family: monospace;
}

.estimator-table summary {
    padding: .5rem;
    cursor: pointer;
}

.estimator-table summary::marker {
    font-size: 0.7rem;
}

.estimator-table details[open] {
    padding-left: 0.1rem;
    padding-right: 0.1rem;
    padding-bottom: 0.3rem;
}

.estimator-table .parameters-table {
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 0;
}

.estimator-table .parameters-table tr:nth-child(odd) {
    background-color: #fff;
}

.estimator-table .parameters-table tr:nth-child(even) {
    background-color: #f6f6f6;
}

.estimator-table .parameters-table tr:hover td {
    background-color: #e0e0e0;
}

.estimator-table table :is(td, th) {
    border: 1px solid rgba(106, 105, 104, 0.232);
}

/\*
    \`table td\`is set in notebook with right text-align.
    We need to overwrite it.
\*/
.estimator-table table td.param {
    text-align: left;
    position: relative;
    padding: 0;
}

.user-set td {
    color:rgb(255, 94, 0);
    text-align: left !important;
}

.user-set td.value {
    color:rgb(255, 94, 0);
    background-color: transparent;
}

.default td, .estimator-table th {
    color: black;
    text-align: left !important;
}

.user-set td i,
.default td i {
    color: black;
}

td.fitted-att-type {
    white-space: preserve nowrap;
}

/\*
    Styles for parameter documentation links
    We need styling for visited so jupyter doesn't overwrite it
\*/
a.param-doc-link,
a.param-doc-link:link,
a.param-doc-link:visited {
    text-decoration: underline dashed;
    text-underline-offset: .3em;
    color: inherit;
    display: block;
    padding: .5em;
}

@supports(anchor-name: --doc-link) {
    a.param-doc-link,
    a.param-doc-link:link,
    a.param-doc-link:visited {
    anchor-name: --doc-link;
    }
}

/\* "hack" to make the entire area of the cell containing the link clickable \*/
a.param-doc-link::before {
    position: absolute;
    content: "";
    inset: 0;
}

.param-doc-description {
    display: none;
    position: absolute;
    z-index: 9999;
    left: 0;
    padding: .5ex;
    margin-left: 1.5em;
    color: var(--sklearn-color-text);
    box-shadow: .3em .3em .4em #999;
    width: max-content;
    text-align: left;
    max-height: 10em;
    overflow-y: auto;

    /\* unfitted \*/
    background: var(--sklearn-color-unfitted-level-0);
    border: thin solid var(--sklearn-color-unfitted-level-3);
}

@supports(position-area: center right) {
    .param-doc-description {
    position-area: center right;
    position: fixed;
    margin-left: 0;
    }
}

/\* Fitted state for parameter tooltips \*/
.fitted .param-doc-description {
    /\* fitted \*/
    background: var(--sklearn-color-fitted-level-0);
    border: thin solid var(--sklearn-color-fitted-level-3);
}

.param-doc-link:hover .param-doc-description {
    display: block;
}

.copy-paste-icon {
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNy4yIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjUgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTIwOCAwTDMzMi4xIDBjMTIuNyAwIDI0LjkgNS4xIDMzLjkgMTQuMWw2Ny45IDY3LjljOSA5IDE0LjEgMjEuMiAxNC4xIDMzLjlMNDQ4IDMzNmMwIDI2LjUtMjEuNSA0OC00OCA0OGwtMTkyIDBjLTI2LjUgMC00OC0yMS41LTQ4LTQ4bDAtMjg4YzAtMjYuNSAyMS41LTQ4IDQ4LTQ4ek00OCAxMjhsODAgMCAwIDY0LTY0IDAgMCAyNTYgMTkyIDAgMC0zMiA2NCAwIDAgNDhjMCAyNi41LTIxLjUgNDgtNDggNDhMNDggNTEyYy0yNi41IDAtNDgtMjEuNS00OC00OEwwIDE3NmMwLTI2LjUgMjEuNS00OCA0OC00OHoiLz48L3N2Zz4=);
    background-repeat: no-repeat;
    background-size: 14px 14px;
    background-position: 0;
    display: inline-block;
    width: 14px;
    height: 14px;
    cursor: pointer;
    border: none;
    padding: 0;
    background-color: transparent;
}

.copy-paste-icon:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 1px;
}

.features {
  font-family: monospace;
  cursor: pointer;
  background-color: var(--sklearn-color-unfitted-level-0);
  border: 1px dotted var(--sklearn-color-border-box);
  border-radius: .20em;
  margin-bottom: 0.5em;
  font-size: inherit; /\* Needed for jupyter \*/
}

.features.fitted {
  background-color: var(--sklearn-color-fitted-level-0);
}

.features summary {
  cursor: pointer;
  display: flex;
  margin-bottom: 0;
  text-align: center;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: .25em;
}

.features details[open] > summary {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-unfitted-level-2);
  border-radius: .20em 0 0 0;
}

.features.fitted details[open] > summary {
  background-color: var(--sklearn-color-fitted-level-2);
  border-radius: .20em 0 0 0;
}

.features details > summary .arrow::before {
  content: "▸";
  color: grey;
}

.features details[open] > summary .arrow::before {
  content: "▾";
}

.features details:hover > summary {
  margin: 0;
  background-color: var(--sklearn-color-unfitted-level-2);
}

.features.fitted details:hover > summary {
  margin: 0;
  background-color: var(--sklearn-color-fitted-level-2);
}

.features .features-container {
  max-height: 10em;
  overflow: auto;
  scrollbar-width: thin;
  padding: .25em 0.1rem;
  background-color: var(--sklearn-color-unfitted-level-0);
  border-radius: 0 0 .5em .5em;
}

.features.fitted .features-container {
  background-color: var(--sklearn-color-fitted-level-0);
}

.features .image-container {
  block-size: 1em;
  inline-size: 1em;
  padding: 0;
  margin: 0%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.features .copy-paste-icon {
  background-size: 1em 1em;
  width: 1em;
  height: 1em;
  filter: grayscale(100%) opacity(60%);
}

.features .features-container table {
  width: 100%;
  margin: 0.01em;
}

.features .features-container table tr:nth-child(odd) {
  background-color: #fff;
}

.features .features-container table tr:nth-child(even) {
  background-color: #f6f6f6;
}

.features .features-container table tr:hover {
  background-color: #e0e0e0;
}

.features .features-container table {
  table-layout: inherit;
}

.features .features-container table td {
  text-align: left;
  padding: 0 0.5em;
  border: 1px solid rgba(106, 105, 104, 0.232);
  white-space: nowrap;
  color: var(--sklearn-color-text);
}

.total_features {
  display: flex;
  justify-content: center;
  margin-top: 0.5em;
}
</style><body><div id="sk-container-id-5" tabindex="0" class="sk-top-container sk-global"><div class="sk-text-repr-fallback"><pre>OnlineGridSearch(estimator=RegimeAdjustedEWCovariance(), n_jobs=-1,
                 param_grid={&#x27;corr_half_life&#x27;: [40, 80],
                             &#x27;half_life&#x27;: [20, 40, 60],
                             &#x27;regime_half_life&#x27;: [10, 20]},
                 scoring=make_scorer(portfolio_variance_qlike_loss, greater_is_better=False, response_method=None),
                 test_size=5)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class="sk-container" hidden><div class="sk-item sk-dashed-wrapped"><div class="sk-label-container"><div class="sk-label fitted sk-toggleable"><input class="sk-toggleable_\_control sk-hidden--visually sk-global" id="sk-estimator-id-28" type="checkbox" ><label for="sk-estimator-id-28" class="sk-toggleable_\_label fitted sk-toggleable_\_label-arrow"><div><div>OnlineGridSearch</div></div><div><span class="sk-estimator-doc-link fitted">i<span>Fitted</span></span></div></label><div class="sk-toggleable_\_content fitted" data-param-prefix="">
        <div class="estimator-table">
            <details>
                <summary>Parameters</summary>
                <table class="parameters-table">
                  <tbody>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy estimator to clipboard"
                 onclick="copyToClipboard('estimator',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">estimator</td>
            <td class="value">RegimeAdjustedEWCovariance()</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy param_grid to clipboard"
                 onclick="copyToClipboard('param_grid',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">param_grid</td>
            <td class="value">{&#x27;corr_half_life&#x27;: [40, 80], &#x27;half_life&#x27;: [20, 40, ...], &#x27;regime_half_life&#x27;: [10, 20]}</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy scoring to clipboard"
                 onclick="copyToClipboard('scoring',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">scoring</td>
            <td class="value">make_scorer(p...e_method=None)</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy test_size to clipboard"
                 onclick="copyToClipboard('test_size',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">test_size</td>
            <td class="value">5</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy n_jobs to clipboard"
                 onclick="copyToClipboard('n_jobs',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">n_jobs</td>
            <td class="value">-1</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy warmup_size to clipboard"
                 onclick="copyToClipboard('warmup_size',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">warmup_size</td>
            <td class="value">252</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy freq to clipboard"
                 onclick="copyToClipboard('freq',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">freq</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy freq_offset to clipboard"
                 onclick="copyToClipboard('freq_offset',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">freq_offset</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy previous to clipboard"
                 onclick="copyToClipboard('previous',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">previous</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy purged_size to clipboard"
                 onclick="copyToClipboard('purged_size',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">purged_size</td>
            <td class="value">0</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy reduce_test to clipboard"
                 onclick="copyToClipboard('reduce_test',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">reduce_test</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy refit to clipboard"
                 onclick="copyToClipboard('refit',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">refit</td>
            <td class="value">True</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy error_score to clipboard"
                 onclick="copyToClipboard('error_score',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">error_score</td>
            <td class="value">nan</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy return_predictions to clipboard"
                 onclick="copyToClipboard('return_predictions',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">return_predictions</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy portfolio_params to clipboard"
                 onclick="copyToClipboard('portfolio_params',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">portfolio_params</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy entry_rebalancing_params to clipboard"
                 onclick="copyToClipboard('entry_rebalancing_params',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">entry_rebalancing_params</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy verbose to clipboard"
                 onclick="copyToClipboard('verbose',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">verbose</td>
            <td class="value">0</td>
        </tr>

                  </tbody>
                </table>
            </details>
        </div>

        <div class="estimator-table">
            <details>
                <summary>Fitted attributes</summary>
                <table class="parameters-table">
                    <tbody>
                        <tr>
                        <th>Name</th>
                        <th>Type</th>
                        <th>Value</th>
                        </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_estimator_</a></td>
           <td class="fitted-att-type">RegimeAdjustedEWCovariance</td>
           <td>RegimeAdjuste..._half_life=10)</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_index_</a></td>
           <td class="fitted-att-type">int</td>
           <td>10</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_params_</a></td>
           <td class="fitted-att-type">dict</td>
           <td>{&#x27;co...fe&#x27;: 80, &#x27;ha...fe&#x27;: 60, &#x27;re...fe&#x27;: 10}</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_score_</a></td>
           <td class="fitted-att-type">float</td>
           <td>6.965</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">cv_results_</a></td>
           <td class="fitted-att-type">dict</td>
           <td>{&#x27;fi...me&#x27;: array([2.8508..., 2.54734196]), &#x27;me...re&#x27;: array([6.9438..., 6.91615991]), &#x27;params&#x27;: [{&#x27;co...fe&#x27;: 40, &#x27;ha...fe&#x27;: 20, &#x27;re...fe&#x27;: 10}, {&#x27;co...fe&#x27;: 40, &#x27;ha...fe&#x27;: 20, &#x27;re...fe&#x27;: 20}, {&#x27;co...fe&#x27;: 40, &#x27;ha...fe&#x27;: 40, &#x27;re...fe&#x27;: 10}, {&#x27;co...fe&#x27;: 40, &#x27;ha...fe&#x27;: 40, &#x27;re...fe&#x27;: 20}, ...], &#x27;rank&#x27;: array([ 6,  8..., dtype=int32)}</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">is_portfolio_estimator_</a></td>
           <td class="fitted-att-type">bool</td>
           <td>False</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">multimetric_</a></td>
           <td class="fitted-att-type">bool</td>
           <td>False</td>

       </tr>

                    </tbody>
                </table>
            </details>
        </div>
    </div></div></div><div class="sk-parallel"><div class="sk-parallel-item"><div class="sk-item"><div class="sk-label-container"><div class="sk-label fitted sk-toggleable"><input class="sk-toggleable_\_control sk-hidden--visually sk-global" id="sk-estimator-id-29" type="checkbox" ><label for="sk-estimator-id-29" class="sk-toggleable_\_label fitted sk-toggleable_\_label-arrow"><div><div>estimator: RegimeAdjustedEWCovariance</div></div></label><div class="sk-toggleable_\_content fitted" data-param-prefix="estimator_\_"><pre>RegimeAdjustedEWCovariance()</pre></div></div></div><div class="sk-serial"><div class="sk-item"><div class="sk-estimator fitted sk-toggleable"><input class="sk-toggleable_\_control sk-hidden--visually sk-global" id="sk-estimator-id-30" type="checkbox" ><label for="sk-estimator-id-30" class="sk-toggleable_\_label fitted sk-toggleable_\_label-arrow"><div><div>RegimeAdjustedEWCovariance</div></div></label><div class="sk-toggleable_\_content fitted" data-param-prefix="estimator_\_">
        <div class="estimator-table">
            <details>
                <summary>Parameters</summary>
                <table class="parameters-table">
                  <tbody>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy half_life to clipboard"
                 onclick="copyToClipboard('half_life',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">half_life</td>
            <td class="value">40</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy corr_half_life to clipboard"
                 onclick="copyToClipboard('corr_half_life',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">corr_half_life</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy hac_lags to clipboard"
                 onclick="copyToClipboard('hac_lags',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">hac_lags</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_half_life to clipboard"
                 onclick="copyToClipboard('regime_half_life',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_half_life</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_target to clipboard"
                 onclick="copyToClipboard('regime_target',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_target</td>
            <td class="value">PORTFOLIO</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_method to clipboard"
                 onclick="copyToClipboard('regime_method',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_method</td>
            <td class="value">FIRST_MOMENT</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_portfolio_weights to clipboard"
                 onclick="copyToClipboard('regime_portfolio_weights',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_portfolio_weights</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_multiplier_clip to clipboard"
                 onclick="copyToClipboard('regime_multiplier_clip',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_multiplier_clip</td>
            <td class="value">(0.7, ...)</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_min_observations to clipboard"
                 onclick="copyToClipboard('regime_min_observations',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_min_observations</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy min_observations to clipboard"
                 onclick="copyToClipboard('min_observations',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">min_observations</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy assume_centered to clipboard"
                 onclick="copyToClipboard('assume_centered',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">assume_centered</td>
            <td class="value">True</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy nearest to clipboard"
                 onclick="copyToClipboard('nearest',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">nearest</td>
            <td class="value">True</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy higham to clipboard"
                 onclick="copyToClipboard('higham',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">higham</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy higham_max_iteration to clipboard"
                 onclick="copyToClipboard('higham_max_iteration',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">higham_max_iteration</td>
            <td class="value">100</td>
        </tr>

                  </tbody>
                </table>
            </details>
        </div>
    </div></div></div></div></div></div></div></div></div></div><script>/\*  Authors: The scikit-learn developers
 SPDX-License-Identifier: BSD-3-Clause
\*/

function copyToClipboard(text, element) {
    // Get the parameter prefix from the closest toggleable content
    const toggleableContent = element.closest('.sk-toggleable_\_content');
    const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';
    const fullParamName = paramPrefix ? \`${paramPrefix}${text}\` : text;

    const originalStyle = element.style;
    const computedStyle = window.getComputedStyle(element);
    const originalWidth = computedStyle.width;
    const originalHTML = element.innerHTML.replace('Copied!', '');

    navigator.clipboard.writeText(fullParamName)
        .then(() => {
            element.style.width = originalWidth;
            element.style.color = 'green';
            element.innerHTML = "Copied!";

            setTimeout(() => {
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 2000);
        })
        .catch(err => {
            console.error('Failed to copy:', err);
            element.style.color = 'red';
            element.innerHTML = "Failed!";
            setTimeout(() => {
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 2000);
        });
    return false;
}

document.querySelectorAll('.copy-paste-icon').forEach(function(element) {
    const toggleableContent = element.closest('.sk-toggleable_\_content');
    const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';

    const parent = element.parentElement;
    if (!parent || !parent.nextElementSibling) {
        console.warn('Expected copy-paste icon is missing from the DOM structure');
        return;
    }

    const paramName = element.parentElement.nextElementSibling
        .textContent.trim().split(' ')[0];
    const fullParamName = paramPrefix ? \`${paramPrefix}${paramName}\` : paramName;

    element.setAttribute('title', fullParamName);
});

/\*\*
 \* Copy the list of feature names formatted as a Python list.
 \*
 \* @param {HTMLElement} element - The copy button inside a \`.features\` block; its siblings
 \*   contain a \`details\` element and a table containing feature named.
 \* @returns {boolean} Always returns \`false\` so callers can prevent the default click behavior.
 \*/
function copyFeatureNamesToClipboard(element) {
    var detailsElem = element.closest('.features').querySelector('details');
    var wasOpen = detailsElem.open;
    detailsElem.open = true;
    var content = element.closest('.features').querySelector('tbody')
                  .innerText.trim();
    if (!wasOpen) detailsElem.open = false;
    const rows = content.split('\\n').map(row => \`    "${row}"\`);
    const formattedText = \`[\\n${rows.join(',\\n')},\\n]\`;
    const originalHTML = element.innerHTML.replace('✔', '');
    const originalStyle = element.style;
    const copyMark = document.createElement('span');
    copyMark.innerHTML = '✔';
    copyMark.style.color = 'blue';
    copyMark.style.fontSize = '1em';

    navigator.clipboard.writeText(formattedText)
        .then(() => {
            element.style.display = 'none';
            element.parentElement.appendChild(copyMark);

            setTimeout(() => {
                copyMark.remove();
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 1000);
        })
        .catch(err => {
            console.error('Failed to copy:', err);
            element.style.color = 'orange';
            element.innerHTML = "Failed!";
            setTimeout(() => {
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 1000);
        });
    return false;
}
/\*\*
 \* Adapted from Skrub
 \* https://github.com/skrub-data/skrub/blob/403466d1d5d4dc76a7ef569b3f8228db59a31dc3/skrub/_reporting/_data/templates/report.js#L789
 \* @returns "light" or "dark"
 \*/
function detectTheme(element) {
    const body = document.querySelector('body');

    // Check VSCode theme
    const themeKindAttr = body.getAttribute('data-vscode-theme-kind');
    const themeNameAttr = body.getAttribute('data-vscode-theme-name');

    if (themeKindAttr && themeNameAttr) {
        const themeKind = themeKindAttr.toLowerCase();
        const themeName = themeNameAttr.toLowerCase();

        if (themeKind.includes("dark") || themeName.includes("dark")) {
            return "dark";
        }
        if (themeKind.includes("light") || themeName.includes("light")) {
            return "light";
        }
    }

    // Check Jupyter theme
    if (body.getAttribute('data-jp-theme-light') === 'false') {
        return 'dark';
    } else if (body.getAttribute('data-jp-theme-light') === 'true') {
        return 'light';
    }

    // Guess based on a parent element's color
    const color = window.getComputedStyle(element.parentNode, null).getPropertyValue('color');
    const match = color.match(/^rgb\\s\*\\(\\s\*(\\d+)\\s\*,\\s\*(\\d+)\\s\*,\\s\*(\\d+)\\s\*\\)\\s\*$/i);
    if (match) {
        const [r, g, b] = [
            parseFloat(match[1]),
            parseFloat(match[2]),
            parseFloat(match[3])
        ];

        // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
        const luma = 0.299 \* r + 0.587 \* g + 0.114 \* b;

        if (luma > 180) {
            // If the text is very bright we have a dark theme
            return 'dark';
        }
        if (luma < 75) {
            // If the text is very dark we have a light theme
            return 'light';
        }
        // Otherwise fall back to the next heuristic.
    }

    // Fallback to system preference
    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

function forceTheme(elementId) {
    const estimatorElement = document.querySelector(\`#${elementId}\`);
    if (estimatorElement === null) {
        console.error(\`Element with id ${elementId} not found.\`);
    } else {
        const theme = detectTheme(estimatorElement);
        estimatorElement.classList.add(theme);
    }
}

forceTheme('sk-container-id-5');</script></body>
</div>
<br />
<br />

Let’s display the best grid-search hyperparameters and score:

```Python
print(f"Grid best params: {grid_search.best_params_}")
print(f"Grid best score: {grid_search.best_score_:.6f}")
```

```none
Grid best params: {'corr_half_life': 80, 'half_life': 60, 'regime_half_life': 10}
Grid best score: 6.964519
```

<a id="onlinerandomizedsearch-with-multi-metric-scoring"></a>

## OnlineRandomizedSearch with Multi-Metric Scoring

We can also use
[`OnlineRandomizedSearch`](https://skfolio.org/generated/skfolio.model_selection.OnlineRandomizedSearch.html.md#skfolio.model_selection.OnlineRandomizedSearch), which samples from
continuous distributions instead of evaluating a full grid. Here, we search
over the same three hyperparameters with 100 random combinations.

We track both QLIKE and calibration loss. Since multi-metric search requires
an explicit selection rule, we set `refit="neg_qlike"` so that the best
estimator is selected according to the QLIKE scorer.

```Python
random_search = OnlineRandomizedSearch(
    estimator=RegimeAdjustedEWCovariance(),
    param_distributions={
        "half_life": uniform(loc=20, scale=40),
        "corr_half_life": uniform(loc=40, scale=40),
        "regime_half_life": uniform(loc=10, scale=10),
    },
    n_iter=100,
    scoring={
        "neg_qlike": qlike_scorer,
        "neg_calibration_loss": calibration_scorer,
    },
    refit="neg_qlike",
    warmup_size=252,
    test_size=5,
    n_jobs=-1,
    random_state=1,
)
random_search.fit(X)
```

<div class="output_subarea output_html rendered_html output_result">
<style>.sk-global {
  /\* Definition of color scheme common for light and dark mode \*/
  --sklearn-color-text: #000;
  --sklearn-color-text-muted: #666;
  --sklearn-color-line: gray;
  /\* Definition of color scheme for unfitted estimators \*/
  --sklearn-color-unfitted-level-0: #fff5e6;
  --sklearn-color-unfitted-level-1: #f6e4d2;
  --sklearn-color-unfitted-level-2: #ffe0b3;
  --sklearn-color-unfitted-level-3: chocolate;
  /\* Definition of color scheme for fitted estimators \*/
  --sklearn-color-fitted-level-0: #f0f8ff;
  --sklearn-color-fitted-level-1: #d4ebff;
  --sklearn-color-fitted-level-2: #b3dbfd;
  --sklearn-color-fitted-level-3: cornflowerblue;
}

.sk-global.light {
  /\* Specific color for light theme \*/
  --sklearn-color-text-on-default-background: black;
  --sklearn-color-background: white;
  --sklearn-color-border-box: black;
  --sklearn-color-icon: #696969;
}

.sk-global.dark {
  --sklearn-color-text-on-default-background: white;
  --sklearn-color-background: #111;
  --sklearn-color-border-box: white;
  --sklearn-color-icon: #878787;
}

.sk-global {
  color: var(--sklearn-color-text);
}

.sk-global pre {
  padding: 0;
}

.sk-global input.sk-hidden--visually {
  border: 0;
  clip-path: inset(100%);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}

.sk-global div.sk-dashed-wrapped {
  border: 1px dashed var(--sklearn-color-line);
  margin: 0 0.4em 0.5em 0.4em;
  box-sizing: border-box;
  padding-bottom: 0.4em;
  background-color: var(--sklearn-color-background);
}

.sk-global div.sk-container {
  /\* jupyter's \`normalize.less\` sets \`[hidden] { display: none; }\`
     but bootstrap.min.css set \`[hidden] { display: none !important; }\`
     so we also need the \`!important\` here to be able to override the
     default hidden behavior on the sphinx rendered scikit-learn.org.
     See: https://github.com/scikit-learn/scikit-learn/issues/21755 \*/
  display: inline-block !important;
  position: relative;
}

.sk-global div.sk-text-repr-fallback {
  display: none;
}

div.sk-parallel-item,
div.sk-serial,
div.sk-item {
  /\* draw centered vertical line to link estimators \*/
  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));
  background-size: 2px 100%;
  background-repeat: no-repeat;
  background-position: center center;
}

/\* Parallel-specific style estimator block \*/

.sk-global div.sk-parallel-item::after {
  content: "";
  width: 100%;
  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);
  flex-grow: 1;
}

.sk-global div.sk-parallel {
  display: flex;
  align-items: stretch;
  justify-content: center;
  background-color: var(--sklearn-color-background);
  position: relative;
}

.sk-global div.sk-parallel-item {
  display: flex;
  flex-direction: column;
}

.sk-global div.sk-parallel-item:first-child::after {
  align-self: flex-end;
  width: 50%;
}

.sk-global div.sk-parallel-item:last-child::after {
  align-self: flex-start;
  width: 50%;
}

.sk-global div.sk-parallel-item:only-child::after {
  width: 0;
}

/\* Serial-specific style estimator block \*/

.sk-global div.sk-serial {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: var(--sklearn-color-background);
  padding-right: 1em;
  padding-left: 1em;
}

/\* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is
clickable and can be expanded/collapsed.
- Pipeline and ColumnTransformer use this feature and define the default style
- Estimators will overwrite some part of the style using the \`sk-estimator\` class
\*/

/\* Pipeline and ColumnTransformer style (default) \*/

.sk-global div.sk-toggleable {
  /\* Default theme specific background. It is overwritten whether we have a
  specific estimator or a Pipeline/ColumnTransformer \*/
  background-color: var(--sklearn-color-background);
}

/\* Toggleable label \*/
.sk-global label.sk-toggleable_\_label {
  cursor: pointer;
  display: flex;
  width: 100%;
  margin-bottom: 0;
  padding: 0.5em;
  box-sizing: border-box;
  text-align: center;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
}

.sk-global label.sk-toggleable_\_label .caption {
  font-size: 0.6rem;
  font-weight: lighter;
  color: var(--sklearn-color-text-muted);
}

.sk-global label.sk-toggleable_\_label-arrow:before {
  /\* Arrow on the left of the label \*/
  content: "▸";
  float: left;
  margin-right: 0.25em;
  color: var(--sklearn-color-icon);
}

.sk-global label.sk-toggleable_\_label-arrow:hover:before {
  color: var(--sklearn-color-text);
}

/\* Toggleable content - dropdown \*/

.sk-global div.sk-toggleable_\_content {
  display: none;
  text-align: left;
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-0);
}

.sk-global div.sk-toggleable_\_content.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
}

.sk-global div.sk-toggleable_\_content pre {
  margin: 0.2em;
  border-radius: 0.25em;
  color: var(--sklearn-color-text);
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-0);
}

.sk-global div.sk-toggleable_\_content.fitted pre {
  /\* unfitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
}

.sk-global input.sk-toggleable_\_control:checked~div.sk-toggleable_\_content {
  /\* Expand drop-down \*/
  display: block;
  width: 100%;
  overflow: visible;
}

.sk-global input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label-arrow:before {
  content: "▾";
}

/\* Pipeline/ColumnTransformer-specific style \*/

.sk-global div.sk-label input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-unfitted-level-2);
}

.sk-global div.sk-label.fitted input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  background-color: var(--sklearn-color-fitted-level-2);
}

/\* Estimator-specific style \*/

/\* Colorize estimator box \*/
.sk-global div.sk-estimator input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-2);
}

.sk-global div.sk-estimator.fitted input.sk-toggleable_\_control:checked~label.sk-toggleable_\_label {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-2);
}

.sk-global div.sk-label label.sk-toggleable_\_label,
.sk-global div.sk-label label {
  /\* The background is the default theme color \*/
  color: var(--sklearn-color-text-on-default-background);
}

/\* On hover, darken the color of the background \*/
.sk-global div.sk-label:hover label.sk-toggleable_\_label {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-unfitted-level-2);
}

/\* Label box, darken color on hover, fitted \*/
.sk-global div.sk-label.fitted:hover label.sk-toggleable_\_label.fitted {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-fitted-level-2);
}

/\* Estimator label \*/

.sk-global div.sk-label label {
  font-family: monospace;
  font-weight: bold;
  line-height: 1.2em;
}

.sk-global div.sk-label-container {
  text-align: center;
}

/\* Estimator-specific \*/
.sk-global div.sk-estimator {
  font-family: monospace;
  border: 1px dotted var(--sklearn-color-border-box);
  border-radius: 0.25em;
  box-sizing: border-box;
  margin-bottom: 0.5em;
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-0);
}

.sk-global div.sk-estimator.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
}

/\* on hover \*/
.sk-global div.sk-estimator:hover {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-2);
}

.sk-global div.sk-estimator.fitted:hover {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-2);
}

/\* Specification for estimator info (e.g. "i" and "?") \*/

/\* Common style for "i" and "?" \*/

.sk-estimator-doc-link,
a:link.sk-estimator-doc-link,
a:visited.sk-estimator-doc-link {
  float: right;
  font-size: smaller;
  line-height: 1em;
  font-family: monospace;
  background-color: var(--sklearn-color-unfitted-level-0);
  border-radius: 1em;
  height: 1em;
  width: 1em;
  text-decoration: none !important;
  margin-left: 0.5em;
  text-align: center;
  /\* unfitted \*/
  border: var(--sklearn-color-unfitted-level-3) 1pt solid;
  color: var(--sklearn-color-unfitted-level-3);
}

.sk-estimator-doc-link.fitted,
a:link.sk-estimator-doc-link.fitted,
a:visited.sk-estimator-doc-link.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
  border: var(--sklearn-color-fitted-level-3) 1pt solid;
  color: var(--sklearn-color-fitted-level-3);
}

/\* On hover \*/
div.sk-estimator:hover .sk-estimator-doc-link:hover,
.sk-estimator-doc-link:hover,
div.sk-label-container:hover .sk-estimator-doc-link:hover,
.sk-estimator-doc-link:hover {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-3);
  border: var(--sklearn-color-fitted-level-0) 1pt solid;
  color: var(--sklearn-color-unfitted-level-0);
  text-decoration: none;
}

div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,
.sk-estimator-doc-link.fitted:hover,
div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,
.sk-estimator-doc-link.fitted:hover {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-3);
  border: var(--sklearn-color-fitted-level-0) 1pt solid;
  color: var(--sklearn-color-fitted-level-0);
  text-decoration: none;
}

/\* Span, style for the box shown on hovering the info icon \*/
.sk-estimator-doc-link span {
  display: none;
  z-index: 9999;
  position: relative;
  font-weight: normal;
  right: .2ex;
  padding: .5ex;
  margin: .5ex;
  width: min-content;
  min-width: 20ex;
  max-width: 50ex;
  color: var(--sklearn-color-text);
  box-shadow: 2pt 2pt 4pt #999;
  /\* unfitted \*/
  background: var(--sklearn-color-unfitted-level-0);
  border: .5pt solid var(--sklearn-color-unfitted-level-3);
}

.sk-estimator-doc-link.fitted span {
  /\* fitted \*/
  background: var(--sklearn-color-fitted-level-0);
  border: var(--sklearn-color-fitted-level-3);
}

.sk-estimator-doc-link:hover span {
  display: block;
}

/\* "?"-specific style due to the \`<a>\` HTML tag \*/

.sk-global a.estimator_doc_link {
  float: right;
  font-size: 1rem;
  line-height: 1em;
  font-family: monospace;
  background-color: var(--sklearn-color-unfitted-level-0);
  border-radius: 1rem;
  height: 1rem;
  width: 1rem;
  text-decoration: none;
  /\* unfitted \*/
  color: var(--sklearn-color-unfitted-level-1);
  border: var(--sklearn-color-unfitted-level-1) 1pt solid;
}

.sk-global a.estimator_doc_link.fitted {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-0);
  border: var(--sklearn-color-fitted-level-1) 1pt solid;
  color: var(--sklearn-color-fitted-level-1);
}

/\* On hover \*/
.sk-global a.estimator_doc_link:hover {
  /\* unfitted \*/
  background-color: var(--sklearn-color-unfitted-level-3);
  color: var(--sklearn-color-background);
  text-decoration: none;
}

.sk-global a.estimator_doc_link.fitted:hover {
  /\* fitted \*/
  background-color: var(--sklearn-color-fitted-level-3);
}

.sk-top-container.sk-global {
  /\* pydata-sphinx-theme hides overflow, so scrolling is disabled.
   We need to set it to !important and add tabindex="0" in the HTML
   to allow keyboard-only users to navigate the display. \*/
  overflow-x: scroll !important;
  max-width: 100%;
}

.estimator-table {
    font-family: monospace;
}

.estimator-table summary {
    padding: .5rem;
    cursor: pointer;
}

.estimator-table summary::marker {
    font-size: 0.7rem;
}

.estimator-table details[open] {
    padding-left: 0.1rem;
    padding-right: 0.1rem;
    padding-bottom: 0.3rem;
}

.estimator-table .parameters-table {
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 0;
}

.estimator-table .parameters-table tr:nth-child(odd) {
    background-color: #fff;
}

.estimator-table .parameters-table tr:nth-child(even) {
    background-color: #f6f6f6;
}

.estimator-table .parameters-table tr:hover td {
    background-color: #e0e0e0;
}

.estimator-table table :is(td, th) {
    border: 1px solid rgba(106, 105, 104, 0.232);
}

/\*
    \`table td\`is set in notebook with right text-align.
    We need to overwrite it.
\*/
.estimator-table table td.param {
    text-align: left;
    position: relative;
    padding: 0;
}

.user-set td {
    color:rgb(255, 94, 0);
    text-align: left !important;
}

.user-set td.value {
    color:rgb(255, 94, 0);
    background-color: transparent;
}

.default td, .estimator-table th {
    color: black;
    text-align: left !important;
}

.user-set td i,
.default td i {
    color: black;
}

td.fitted-att-type {
    white-space: preserve nowrap;
}

/\*
    Styles for parameter documentation links
    We need styling for visited so jupyter doesn't overwrite it
\*/
a.param-doc-link,
a.param-doc-link:link,
a.param-doc-link:visited {
    text-decoration: underline dashed;
    text-underline-offset: .3em;
    color: inherit;
    display: block;
    padding: .5em;
}

@supports(anchor-name: --doc-link) {
    a.param-doc-link,
    a.param-doc-link:link,
    a.param-doc-link:visited {
    anchor-name: --doc-link;
    }
}

/\* "hack" to make the entire area of the cell containing the link clickable \*/
a.param-doc-link::before {
    position: absolute;
    content: "";
    inset: 0;
}

.param-doc-description {
    display: none;
    position: absolute;
    z-index: 9999;
    left: 0;
    padding: .5ex;
    margin-left: 1.5em;
    color: var(--sklearn-color-text);
    box-shadow: .3em .3em .4em #999;
    width: max-content;
    text-align: left;
    max-height: 10em;
    overflow-y: auto;

    /\* unfitted \*/
    background: var(--sklearn-color-unfitted-level-0);
    border: thin solid var(--sklearn-color-unfitted-level-3);
}

@supports(position-area: center right) {
    .param-doc-description {
    position-area: center right;
    position: fixed;
    margin-left: 0;
    }
}

/\* Fitted state for parameter tooltips \*/
.fitted .param-doc-description {
    /\* fitted \*/
    background: var(--sklearn-color-fitted-level-0);
    border: thin solid var(--sklearn-color-fitted-level-3);
}

.param-doc-link:hover .param-doc-description {
    display: block;
}

.copy-paste-icon {
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNy4yIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjUgRm9udGljb25zLCBJbmMuLS0+PHBhdGggZD0iTTIwOCAwTDMzMi4xIDBjMTIuNyAwIDI0LjkgNS4xIDMzLjkgMTQuMWw2Ny45IDY3LjljOSA5IDE0LjEgMjEuMiAxNC4xIDMzLjlMNDQ4IDMzNmMwIDI2LjUtMjEuNSA0OC00OCA0OGwtMTkyIDBjLTI2LjUgMC00OC0yMS41LTQ4LTQ4bDAtMjg4YzAtMjYuNSAyMS41LTQ4IDQ4LTQ4ek00OCAxMjhsODAgMCAwIDY0LTY0IDAgMCAyNTYgMTkyIDAgMC0zMiA2NCAwIDAgNDhjMCAyNi41LTIxLjUgNDgtNDggNDhMNDggNTEyYy0yNi41IDAtNDgtMjEuNS00OC00OEwwIDE3NmMwLTI2LjUgMjEuNS00OCA0OC00OHoiLz48L3N2Zz4=);
    background-repeat: no-repeat;
    background-size: 14px 14px;
    background-position: 0;
    display: inline-block;
    width: 14px;
    height: 14px;
    cursor: pointer;
    border: none;
    padding: 0;
    background-color: transparent;
}

.copy-paste-icon:focus-visible {
    outline: 1px solid currentColor;
    outline-offset: 1px;
}

.features {
  font-family: monospace;
  cursor: pointer;
  background-color: var(--sklearn-color-unfitted-level-0);
  border: 1px dotted var(--sklearn-color-border-box);
  border-radius: .20em;
  margin-bottom: 0.5em;
  font-size: inherit; /\* Needed for jupyter \*/
}

.features.fitted {
  background-color: var(--sklearn-color-fitted-level-0);
}

.features summary {
  cursor: pointer;
  display: flex;
  margin-bottom: 0;
  text-align: center;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: .25em;
}

.features details[open] > summary {
  color: var(--sklearn-color-text);
  background-color: var(--sklearn-color-unfitted-level-2);
  border-radius: .20em 0 0 0;
}

.features.fitted details[open] > summary {
  background-color: var(--sklearn-color-fitted-level-2);
  border-radius: .20em 0 0 0;
}

.features details > summary .arrow::before {
  content: "▸";
  color: grey;
}

.features details[open] > summary .arrow::before {
  content: "▾";
}

.features details:hover > summary {
  margin: 0;
  background-color: var(--sklearn-color-unfitted-level-2);
}

.features.fitted details:hover > summary {
  margin: 0;
  background-color: var(--sklearn-color-fitted-level-2);
}

.features .features-container {
  max-height: 10em;
  overflow: auto;
  scrollbar-width: thin;
  padding: .25em 0.1rem;
  background-color: var(--sklearn-color-unfitted-level-0);
  border-radius: 0 0 .5em .5em;
}

.features.fitted .features-container {
  background-color: var(--sklearn-color-fitted-level-0);
}

.features .image-container {
  block-size: 1em;
  inline-size: 1em;
  padding: 0;
  margin: 0%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.features .copy-paste-icon {
  background-size: 1em 1em;
  width: 1em;
  height: 1em;
  filter: grayscale(100%) opacity(60%);
}

.features .features-container table {
  width: 100%;
  margin: 0.01em;
}

.features .features-container table tr:nth-child(odd) {
  background-color: #fff;
}

.features .features-container table tr:nth-child(even) {
  background-color: #f6f6f6;
}

.features .features-container table tr:hover {
  background-color: #e0e0e0;
}

.features .features-container table {
  table-layout: inherit;
}

.features .features-container table td {
  text-align: left;
  padding: 0 0.5em;
  border: 1px solid rgba(106, 105, 104, 0.232);
  white-space: nowrap;
  color: var(--sklearn-color-text);
}

.total_features {
  display: flex;
  justify-content: center;
  margin-top: 0.5em;
}
</style><body><div id="sk-container-id-6" tabindex="0" class="sk-top-container sk-global"><div class="sk-text-repr-fallback"><pre>OnlineRandomizedSearch(estimator=RegimeAdjustedEWCovariance(), n_iter=100,
                       n_jobs=-1,
                       param_distributions={&#x27;corr_half_life&#x27;: &lt;scipy.stats._distn_infrastructure.rv_continuous_frozen object at 0x7f35f8e3a9f0&gt;,
                                            &#x27;half_life&#x27;: &lt;scipy.stats._distn_infrastructure.rv_continuous_frozen object at 0x7f361ec8e190&gt;,
                                            &#x27;regime_half_life&#x27;: &lt;scipy.stats._distn_infrastructure.rv_continuous_frozen object at 0x7f361cb55ae0&gt;},
                       random_state=1, refit=&#x27;neg_qlike&#x27;,
                       scoring={&#x27;neg_calibration_loss&#x27;: make_scorer(diagonal_calibration_loss, greater_is_better=False, response_method=None),
                                &#x27;neg_qlike&#x27;: make_scorer(portfolio_variance_qlike_loss, greater_is_better=False, response_method=None)},
                       test_size=5)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class="sk-container" hidden><div class="sk-item sk-dashed-wrapped"><div class="sk-label-container"><div class="sk-label fitted sk-toggleable"><input class="sk-toggleable_\_control sk-hidden--visually sk-global" id="sk-estimator-id-31" type="checkbox" ><label for="sk-estimator-id-31" class="sk-toggleable_\_label fitted sk-toggleable_\_label-arrow"><div><div>OnlineRandomizedSearch</div></div><div><span class="sk-estimator-doc-link fitted">i<span>Fitted</span></span></div></label><div class="sk-toggleable_\_content fitted" data-param-prefix="">
        <div class="estimator-table">
            <details>
                <summary>Parameters</summary>
                <table class="parameters-table">
                  <tbody>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy estimator to clipboard"
                 onclick="copyToClipboard('estimator',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">estimator</td>
            <td class="value">RegimeAdjustedEWCovariance()</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy param_distributions to clipboard"
                 onclick="copyToClipboard('param_distributions',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">param_distributions</td>
            <td class="value">{&#x27;corr_half_life&#x27;: &lt;scipy.stats....x7f35f8e3a9f0&gt;, &#x27;half_life&#x27;: &lt;scipy.stats....x7f361ec8e190&gt;, &#x27;regime_half_life&#x27;: &lt;scipy.stats....x7f361cb55ae0&gt;}</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy n_iter to clipboard"
                 onclick="copyToClipboard('n_iter',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">n_iter</td>
            <td class="value">100</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy scoring to clipboard"
                 onclick="copyToClipboard('scoring',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">scoring</td>
            <td class="value">{&#x27;neg_calibration_loss&#x27;: make_scorer(d...e_method=None), &#x27;neg_qlike&#x27;: make_scorer(p...e_method=None)}</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy test_size to clipboard"
                 onclick="copyToClipboard('test_size',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">test_size</td>
            <td class="value">5</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy refit to clipboard"
                 onclick="copyToClipboard('refit',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">refit</td>
            <td class="value">&#x27;neg_qlike&#x27;</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy random_state to clipboard"
                 onclick="copyToClipboard('random_state',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">random_state</td>
            <td class="value">1</td>
        </tr>

        <tr class="user-set">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy n_jobs to clipboard"
                 onclick="copyToClipboard('n_jobs',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">n_jobs</td>
            <td class="value">-1</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy warmup_size to clipboard"
                 onclick="copyToClipboard('warmup_size',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">warmup_size</td>
            <td class="value">252</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy freq to clipboard"
                 onclick="copyToClipboard('freq',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">freq</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy freq_offset to clipboard"
                 onclick="copyToClipboard('freq_offset',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">freq_offset</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy previous to clipboard"
                 onclick="copyToClipboard('previous',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">previous</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy purged_size to clipboard"
                 onclick="copyToClipboard('purged_size',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">purged_size</td>
            <td class="value">0</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy reduce_test to clipboard"
                 onclick="copyToClipboard('reduce_test',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">reduce_test</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy error_score to clipboard"
                 onclick="copyToClipboard('error_score',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">error_score</td>
            <td class="value">nan</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy return_predictions to clipboard"
                 onclick="copyToClipboard('return_predictions',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">return_predictions</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy portfolio_params to clipboard"
                 onclick="copyToClipboard('portfolio_params',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">portfolio_params</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy entry_rebalancing_params to clipboard"
                 onclick="copyToClipboard('entry_rebalancing_params',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">entry_rebalancing_params</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy verbose to clipboard"
                 onclick="copyToClipboard('verbose',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">verbose</td>
            <td class="value">0</td>
        </tr>

                  </tbody>
                </table>
            </details>
        </div>

        <div class="estimator-table">
            <details>
                <summary>Fitted attributes</summary>
                <table class="parameters-table">
                    <tbody>
                        <tr>
                        <th>Name</th>
                        <th>Type</th>
                        <th>Value</th>
                        </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_estimator_</a></td>
           <td class="fitted-att-type">RegimeAdjustedEWCovariance</td>
           <td>RegimeAdjuste...870327031159))</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_index_</a></td>
           <td class="fitted-att-type">int</td>
           <td>32</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_params_</a></td>
           <td class="fitted-att-type">dict</td>
           <td>{&#x27;co...fe&#x27;: np.float64(76.13518082249016), &#x27;ha...fe&#x27;: np.float64(42.947179466891434), &#x27;re...fe&#x27;: np.float64(10.02870327031159)}</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">best_score_</a></td>
           <td class="fitted-att-type">float</td>
           <td>6.963</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">cv_results_</a></td>
           <td class="fitted-att-type">dict</td>
           <td>{&#x27;fi...me&#x27;: array([2.9584..., 2.54143798]), &#x27;me...ss&#x27;: array([-0.698... -0.67928287]), &#x27;me...ke&#x27;: array([6.9607..., 6.95152264]), &#x27;params&#x27;: [{&#x27;co...fe&#x27;: np.float64(56.68088018810296), &#x27;ha...fe&#x27;: np.float64(48.81297973768632), &#x27;re...fe&#x27;: np.float64(10.00114374817345)}, {&#x27;co...fe&#x27;: np.float64(52.09330290527359), &#x27;ha...fe&#x27;: np.float64(25.870235632684523), &#x27;re...fe&#x27;: np.float64(10.923385947687978)}, {&#x27;co...fe&#x27;: np.float64(47.45040845510684), &#x27;ha...fe&#x27;: np.float64(33.82242908172191), &#x27;re...fe&#x27;: np.float64(13.967674742306698)}, {&#x27;co...fe&#x27;: np.float64(61.552669360134274), &#x27;ha...fe&#x27;: np.float64(36.76778057613179), &#x27;re...fe&#x27;: np.float64(16.852195003967594)}, ...], ...}</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">is_portfolio_estimator_</a></td>
           <td class="fitted-att-type">bool</td>
           <td>False</td>

       </tr>

       <tr class="default">
           <td class="param"><a class="param-doc-link" style="text-decoration:none;">multimetric_</a></td>
           <td class="fitted-att-type">bool</td>
           <td>True</td>

       </tr>

                    </tbody>
                </table>
            </details>
        </div>
    </div></div></div><div class="sk-parallel"><div class="sk-parallel-item"><div class="sk-item"><div class="sk-label-container"><div class="sk-label fitted sk-toggleable"><input class="sk-toggleable_\_control sk-hidden--visually sk-global" id="sk-estimator-id-32" type="checkbox" ><label for="sk-estimator-id-32" class="sk-toggleable_\_label fitted sk-toggleable_\_label-arrow"><div><div>estimator: RegimeAdjustedEWCovariance</div></div></label><div class="sk-toggleable_\_content fitted" data-param-prefix="estimator_\_"><pre>RegimeAdjustedEWCovariance()</pre></div></div></div><div class="sk-serial"><div class="sk-item"><div class="sk-estimator fitted sk-toggleable"><input class="sk-toggleable_\_control sk-hidden--visually sk-global" id="sk-estimator-id-33" type="checkbox" ><label for="sk-estimator-id-33" class="sk-toggleable_\_label fitted sk-toggleable_\_label-arrow"><div><div>RegimeAdjustedEWCovariance</div></div></label><div class="sk-toggleable_\_content fitted" data-param-prefix="estimator_\_">
        <div class="estimator-table">
            <details>
                <summary>Parameters</summary>
                <table class="parameters-table">
                  <tbody>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy half_life to clipboard"
                 onclick="copyToClipboard('half_life',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">half_life</td>
            <td class="value">40</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy corr_half_life to clipboard"
                 onclick="copyToClipboard('corr_half_life',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">corr_half_life</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy hac_lags to clipboard"
                 onclick="copyToClipboard('hac_lags',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">hac_lags</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_half_life to clipboard"
                 onclick="copyToClipboard('regime_half_life',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_half_life</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_target to clipboard"
                 onclick="copyToClipboard('regime_target',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_target</td>
            <td class="value">PORTFOLIO</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_method to clipboard"
                 onclick="copyToClipboard('regime_method',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_method</td>
            <td class="value">FIRST_MOMENT</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_portfolio_weights to clipboard"
                 onclick="copyToClipboard('regime_portfolio_weights',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_portfolio_weights</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_multiplier_clip to clipboard"
                 onclick="copyToClipboard('regime_multiplier_clip',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_multiplier_clip</td>
            <td class="value">(0.7, ...)</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy regime_min_observations to clipboard"
                 onclick="copyToClipboard('regime_min_observations',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">regime_min_observations</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy min_observations to clipboard"
                 onclick="copyToClipboard('min_observations',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">min_observations</td>
            <td class="value">None</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy assume_centered to clipboard"
                 onclick="copyToClipboard('assume_centered',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">assume_centered</td>
            <td class="value">True</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy nearest to clipboard"
                 onclick="copyToClipboard('nearest',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">nearest</td>
            <td class="value">True</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy higham to clipboard"
                 onclick="copyToClipboard('higham',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">higham</td>
            <td class="value">False</td>
        </tr>

        <tr class="default">
            <td><button type="button" class="copy-paste-icon"
                 aria-label="Copy higham_max_iteration to clipboard"
                 onclick="copyToClipboard('higham_max_iteration',
                          this.parentElement.nextElementSibling)"
            ></button></td>
            <td class="param">higham_max_iteration</td>
            <td class="value">100</td>
        </tr>

                  </tbody>
                </table>
            </details>
        </div>
    </div></div></div></div></div></div></div></div></div></div><script>/\*  Authors: The scikit-learn developers
 SPDX-License-Identifier: BSD-3-Clause
\*/

function copyToClipboard(text, element) {
    // Get the parameter prefix from the closest toggleable content
    const toggleableContent = element.closest('.sk-toggleable_\_content');
    const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';
    const fullParamName = paramPrefix ? \`${paramPrefix}${text}\` : text;

    const originalStyle = element.style;
    const computedStyle = window.getComputedStyle(element);
    const originalWidth = computedStyle.width;
    const originalHTML = element.innerHTML.replace('Copied!', '');

    navigator.clipboard.writeText(fullParamName)
        .then(() => {
            element.style.width = originalWidth;
            element.style.color = 'green';
            element.innerHTML = "Copied!";

            setTimeout(() => {
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 2000);
        })
        .catch(err => {
            console.error('Failed to copy:', err);
            element.style.color = 'red';
            element.innerHTML = "Failed!";
            setTimeout(() => {
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 2000);
        });
    return false;
}

document.querySelectorAll('.copy-paste-icon').forEach(function(element) {
    const toggleableContent = element.closest('.sk-toggleable_\_content');
    const paramPrefix = toggleableContent ? toggleableContent.dataset.paramPrefix : '';

    const parent = element.parentElement;
    if (!parent || !parent.nextElementSibling) {
        console.warn('Expected copy-paste icon is missing from the DOM structure');
        return;
    }

    const paramName = element.parentElement.nextElementSibling
        .textContent.trim().split(' ')[0];
    const fullParamName = paramPrefix ? \`${paramPrefix}${paramName}\` : paramName;

    element.setAttribute('title', fullParamName);
});

/\*\*
 \* Copy the list of feature names formatted as a Python list.
 \*
 \* @param {HTMLElement} element - The copy button inside a \`.features\` block; its siblings
 \*   contain a \`details\` element and a table containing feature named.
 \* @returns {boolean} Always returns \`false\` so callers can prevent the default click behavior.
 \*/
function copyFeatureNamesToClipboard(element) {
    var detailsElem = element.closest('.features').querySelector('details');
    var wasOpen = detailsElem.open;
    detailsElem.open = true;
    var content = element.closest('.features').querySelector('tbody')
                  .innerText.trim();
    if (!wasOpen) detailsElem.open = false;
    const rows = content.split('\\n').map(row => \`    "${row}"\`);
    const formattedText = \`[\\n${rows.join(',\\n')},\\n]\`;
    const originalHTML = element.innerHTML.replace('✔', '');
    const originalStyle = element.style;
    const copyMark = document.createElement('span');
    copyMark.innerHTML = '✔';
    copyMark.style.color = 'blue';
    copyMark.style.fontSize = '1em';

    navigator.clipboard.writeText(formattedText)
        .then(() => {
            element.style.display = 'none';
            element.parentElement.appendChild(copyMark);

            setTimeout(() => {
                copyMark.remove();
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 1000);
        })
        .catch(err => {
            console.error('Failed to copy:', err);
            element.style.color = 'orange';
            element.innerHTML = "Failed!";
            setTimeout(() => {
                element.innerHTML = originalHTML;
                element.style = originalStyle;
            }, 1000);
        });
    return false;
}
/\*\*
 \* Adapted from Skrub
 \* https://github.com/skrub-data/skrub/blob/403466d1d5d4dc76a7ef569b3f8228db59a31dc3/skrub/_reporting/_data/templates/report.js#L789
 \* @returns "light" or "dark"
 \*/
function detectTheme(element) {
    const body = document.querySelector('body');

    // Check VSCode theme
    const themeKindAttr = body.getAttribute('data-vscode-theme-kind');
    const themeNameAttr = body.getAttribute('data-vscode-theme-name');

    if (themeKindAttr && themeNameAttr) {
        const themeKind = themeKindAttr.toLowerCase();
        const themeName = themeNameAttr.toLowerCase();

        if (themeKind.includes("dark") || themeName.includes("dark")) {
            return "dark";
        }
        if (themeKind.includes("light") || themeName.includes("light")) {
            return "light";
        }
    }

    // Check Jupyter theme
    if (body.getAttribute('data-jp-theme-light') === 'false') {
        return 'dark';
    } else if (body.getAttribute('data-jp-theme-light') === 'true') {
        return 'light';
    }

    // Guess based on a parent element's color
    const color = window.getComputedStyle(element.parentNode, null).getPropertyValue('color');
    const match = color.match(/^rgb\\s\*\\(\\s\*(\\d+)\\s\*,\\s\*(\\d+)\\s\*,\\s\*(\\d+)\\s\*\\)\\s\*$/i);
    if (match) {
        const [r, g, b] = [
            parseFloat(match[1]),
            parseFloat(match[2]),
            parseFloat(match[3])
        ];

        // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
        const luma = 0.299 \* r + 0.587 \* g + 0.114 \* b;

        if (luma > 180) {
            // If the text is very bright we have a dark theme
            return 'dark';
        }
        if (luma < 75) {
            // If the text is very dark we have a light theme
            return 'light';
        }
        // Otherwise fall back to the next heuristic.
    }

    // Fallback to system preference
    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

function forceTheme(elementId) {
    const estimatorElement = document.querySelector(\`#${elementId}\`);
    if (estimatorElement === null) {
        console.error(\`Element with id ${elementId} not found.\`);
    } else {
        const theme = detectTheme(estimatorElement);
        estimatorElement.classList.add(theme);
    }
}

forceTheme('sk-container-id-6');</script></body>
</div>
<br />
<br />

Let’s display the best randomized-search hyperparameters and score:

```Python
print(f"Random best params: {random_search.best_params_}")
print(f"Random best score (neg_qlike): {random_search.best_score_:.6f}")
```

```none
Random best params: {'corr_half_life': np.float64(76.13518082249016), 'half_life': np.float64(42.947179466891434), 'regime_half_life': np.float64(10.02870327031159)}
Random best score (neg_qlike): 6.963007
```

<a id="online-score"></a>

## Online Score

`OnlineRandomizedSearch` already stores the aggregate online scores of all
sampled candidates in `cv_results_`. We use
[`online_score`](https://skfolio.org/generated/skfolio.model_selection.online_score.html.md#skfolio.model_selection.online_score) below only to evaluate a baseline
specification that was not part of the search. This also illustrates the
standalone scoring API.

```Python
baseline_cov = RegimeAdjustedEWCovariance(
    half_life=40,
    corr_half_life=80,
    regime_half_life=20,
)
cv_results = random_search.cv_results_
best_idx = random_search.best_index_

baseline_scores = online_score(
    baseline_cov,
    X,
    warmup_size=252,
    test_size=5,
    scoring={
        "neg_qlike": qlike_scorer,
        "neg_calibration_loss": calibration_scorer,
    },
)
tuned_scores = {
    "neg_qlike": cv_results["mean_score_neg_qlike"][best_idx],
    "neg_calibration_loss": cv_results["mean_score_neg_calibration_loss"][best_idx],
}
```

Let’s compare the baseline and tuned scores. The tuned scores are retrieved
directly from the search results, while the baseline is scored separately with
[`online_score`](https://skfolio.org/generated/skfolio.model_selection.online_score.html.md#skfolio.model_selection.online_score). Since the scorers negate the
losses, higher values indicate better performance:

```Python
print("Baseline scores:")
print(baseline_scores)
print("Tuned scores:")
print(tuned_scores)
```

```none
Baseline scores:
{'neg_qlike': 6.92239803023065, 'neg_calibration_loss': -0.7392869425387291}
Tuned scores:
{'neg_qlike': np.float64(6.963007268601512), 'neg_calibration_loss': np.float64(-0.7197863505305562)}
```

<a id="search-trade-off-plot"></a>

## Search Trade-Off Plot

The scatter plot below summarizes the aggregate online losses of the 100
sampled parameter combinations, with the selected candidate highlighted and
the baseline shown for reference.

```Python
results = pd.DataFrame(cv_results["params"])
results["qlike_loss"] = -cv_results["mean_score_neg_qlike"]
results["calibration_loss"] = -cv_results["mean_score_neg_calibration_loss"]

fig = px.scatter(
    results,
    x="qlike_loss",
    y="calibration_loss",
    color="regime_half_life",
    hover_data=["half_life", "corr_half_life", "regime_half_life"],
    color_continuous_scale="Viridis",
    labels={
        "qlike_loss": "QLIKE loss",
        "calibration_loss": "Diagonal calibration loss",
        "regime_half_life": "Regime half-life",
    },
    title="Online Random Search: QLIKE vs Calibration Loss",
)
fig.update_traces(marker=dict(size=9, opacity=0.75, line=dict(width=0)))

fig.add_trace(
    go.Scatter(
        x=[results.loc[best_idx, "qlike_loss"]],
        y=[results.loc[best_idx, "calibration_loss"]],
        mode="markers+text",
        name="Selected candidate",
        text=["Selected"],
        textposition="top right",
        marker=dict(symbol="star", size=16, color="green", line=dict(width=1)),
        showlegend=False,
    )
)
fig.add_trace(
    go.Scatter(
        x=[-baseline_scores["neg_qlike"]],
        y=[-baseline_scores["neg_calibration_loss"]],
        mode="markers+text",
        name="Baseline",
        text=["Baseline"],
        textposition="bottom right",
        marker=dict(symbol="x", size=13, color="black", line=dict(width=2)),
        showlegend=False,
    )
)
show(fig)
```

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

<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:** (1 minutes 28.993 seconds)

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