<a id="skfolio-model-selection-online-score"></a>

# skfolio.model_selection.online_score

<a id="skfolio.model_selection.online_score"></a>

### skfolio.model_selection.online_score(estimator, X, y=None, warmup_size=252, test_size=1, freq=None, freq_offset=None, previous=False, purged_size=0, reduce_test=False, scoring=None, params=None, per_step=False, portfolio_params=None, entry_rebalancing_params=None)

Score an online estimator using walk-forward evaluation.

Walks forward through the data, updating the estimator incrementally via
`partial_fit` and scoring on each subsequent test window. This is the scoring
counterpart of [`online_predict`](https://skfolio.org/generated/skfolio.model_selection.online_predict.html.md#skfolio.model_selection.online_predict).

The function handles both *non-predictor estimators* (e.g. covariance, expected
returns, prior) and *portfolio optimization* estimators:

* **non-predictor estimators** are scored on each test window independently.
  By default the average of per-step scores is returned.
* **Portfolio optimization estimators** are evaluated by collecting out-of-sample
  predictions into a [`MultiPeriodPortfolio`](https://skfolio.org/generated/skfolio.portfolio.MultiPeriodPortfolio.html.md#skfolio.portfolio.MultiPeriodPortfolio) and computing
  the requested measure on the full multi-period portfolio.

* **Parameters:**
  **estimator** *BaseEstimator*
  : Estimator instance to use to fit the data. It must implement `partial_fit`.
    Pipelines are not supported.

  **X** *array-like of shape (n_observations, n_assets)*
  : Price returns of the assets. Must be a DataFrame with a `DatetimeIndex` when
    `freq` is provided.

  **y** *array-like of shape (n_observations, n_targets), optional*
  : Target data to pass to `partial_fit`.

  **warmup_size** *int, default=252*
  : Number of initial observations (or periods when `freq` is set) used for the
    first `partial_fit` call. No scores are produced during warmup.

  **test_size** *int, default=1*
  : Length of each test set.
    If `freq` is `None` (default), it represents the number of observations.
    Otherwise, it represents the number of periods defined by `freq`.

  **freq** *str | pandas.offsets.BaseOffset, optional*
  : If provided, it must be a frequency string or a pandas DateOffset, and `X` must
    be a DataFrame with an index of type `DatetimeIndex`. In that case,
    `warmup_size` and `test_size` represent the number of periods defined by `freq`
    instead of the number of observations.

  **freq_offset** *pandas.offsets.BaseOffset | datetime.timedelta, optional*
  : Only used if `freq` is provided. Offsets `freq` by a pandas DateOffset or a
    datetime timedelta offset.

  **previous** *bool, default=False*
  : Only used if `freq` is provided. If set to `True`, and if the period start or
    period end is not in the `DatetimeIndex`, the previous observation is used;
    otherwise, the next observation is used.

  **purged_size** *int, default=0*
  : The number of observations to exclude from the end of each training
    window before the test window.

  **reduce_test** *bool, default=False*
  : If set to `True`, the last test window is returned even if it is partial,
    otherwise it is ignored.

  **scoring** *callable, dict, BaseMeasure, or None*
  : Scoring specification. Semantics depend on the estimator type:
    * **Non-predictor estimators** (e.g. covariance, expected returns, prior):
      `None` uses `estimator.score`; otherwise pass a callable
      scorer(estimator, X_test)\` or a dict of such callables.
    * **Portfolio optimization estimators**:
      a [`BaseMeasure`](https://skfolio.org/generated/skfolio.measures.BaseMeasure.html.md#skfolio.measures.BaseMeasure) or a dict of measures. `None`
      defaults to `SHARPE_RATIO`.
    <br/>
    #### NOTE
    For portfolio optimization estimators, online evaluation scores the
    aggregated out-of-sample [`MultiPeriodPortfolio`](https://skfolio.org/generated/skfolio.portfolio.MultiPeriodPortfolio.html.md#skfolio.portfolio.MultiPeriodPortfolio),
    rather than scoring each test window independently and averaging as in
    `GridSearchCV`. Pass the measure enum
    directly; `make_scorer` is not supported.

  **params** *dict, optional*
  : Parameters to pass to the underlying estimator’s `partial_fit`
    through metadata routing.

  **per_step** *bool, default=False*
  : If `True`, return per-step score arrays instead of aggregated
    scalars. Only supported for non-predictor estimators; raises
    `ValueError` for portfolio optimization estimators.

  **portfolio_params** *dict, optional*
  : Portfolio parameters for the evaluation of a portfolio optimizer.
    <br/>
    Parameters shared by [`Portfolio`](https://skfolio.org/generated/skfolio.portfolio.Portfolio.html.md#skfolio.portfolio.Portfolio) and
    [`MultiPeriodPortfolio`](https://skfolio.org/generated/skfolio.portfolio.MultiPeriodPortfolio.html.md#skfolio.portfolio.MultiPeriodPortfolio) (`compounded`,
    `risk_free_rate`, `annualization_factor`, `fitness_measures` and the risk
    measure parameters) are applied to the scored `MultiPeriodPortfolio` and to
    each `Portfolio` it contains. A value passed here takes precedence over the
    optimizer’s `portfolio_params`. When omitted here, it is inherited from the
    optimizer’s `portfolio_params`. When omitted from both, `risk_free_rate` falls
    back to the optimizer’s `risk_free_rate` parameter when it has one. These
    parameters only affect how the portfolios are measured, not the optimization,
    so they can change the score.
    <br/>
    `weight_drift` applies to each `Portfolio` of the path. With
    `weight_drift=True`, the weights held within each test window drift with the
    asset returns, and the path runs sequentially: the `ending_weights` of each
    portfolio are passed as `previous_weights` to the next update. A value passed
    here overrides the optimizer’s `portfolio_params`.
    Failed and empty portfolios do not update the previous holdings.
    <br/>
    Optimizer parameters such as `transaction_costs`, `management_fees` and
    `previous_weights` are not accepted here. Set them on the optimizer.
    <br/>
    `name`, `tag`, `sample_weight` and `check_observations_order` apply to the
    scored `MultiPeriodPortfolio` only.

  **entry_rebalancing_params** *dict, optional*
  : Portfolio optimizer parameters applied only while constructing its first
    portfolio. This is useful when the strategy starts with no existing position,
    while later portfolios represent regular rebalancing from the previously
    predicted weights. For example, the entry rebalancing can relax `max_turnover`
    or use lower `transaction_costs` to avoid a slow ramp from cash caused by
    recurring rebalancing constraints. The regular optimizer parameters are
    restored before the next online update.
* **Returns:**
  **score** *float | dict[str, float] | ndarray | dict[str, ndarray]*
  : By default, an aggregate `float` (or `dict` for multi-metric).
    When `per_step=True`, a `FloatArray` of per-step scores (or
    `dict` thereof).
* **Raises:**
  TypeError
  : If the estimator does not implement `partial_fit` or is a pipeline.

  ValueError
  : If `per_step=True` is used with a portfolio optimization estimator,
    or if `warmup_size < 1`, `test_size < 1`, or the data is too
    short for at least one test window.

#### SEE ALSO
[Online Covariance Hyperparameter Tuning](https://skfolio.org/auto_examples/online_learning/plot_2_online_hyperparameter_tuning.html.md#sphx-glr-auto-examples-online-learning-plot-2-online-hyperparameter-tuning-py)
: Programmatic comparison of covariance estimators with `online_score`.

[Online Evaluation of Portfolio Optimization](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)
: Portfolio-level evaluation with `online_score`.

### Examples

non-predictor estimator (default `estimator.score`):

```pycon
>>> from skfolio.datasets import load_sp500_dataset
>>> from skfolio.model_selection import online_score
>>> from skfolio.moments import EWCovariance
>>> from skfolio.preprocessing import prices_to_returns
>>>
>>> prices = load_sp500_dataset()
>>> X = prices_to_returns(prices).tail(504)
>>> score = online_score(EWCovariance(), X, warmup_size=252)
```

Portfolio optimization estimator:

```pycon
>>> from skfolio.measures import RatioMeasure
>>> from skfolio.moments import EWMu
>>> from skfolio.optimization import MeanRisk
>>> from skfolio.prior import EmpiricalPrior
>>>
>>> model = MeanRisk(
...     prior_estimator=EmpiricalPrior(
...         mu_estimator=EWMu(half_life=40),
...         covariance_estimator=EWCovariance(half_life=40),
...     ),
... )
>>> score = online_score(
...     model,
...     X,
...     warmup_size=252,
...     test_size=5,
...     scoring=RatioMeasure.SHARPE_RATIO,
... )
```

