skfolio.uncertainty_set.OrthogonalCovarianceUncertaintySet#

class skfolio.uncertainty_set.OrthogonalCovarianceUncertaintySet(radius=1.0, cs_weighting=INVERSE_IDIO_VARIANCE)[source]#

Covariance uncertainty set estimator for directions outside the factor span.

This estimator builds a compact covariance uncertainty set for robust portfolio optimization [1] [2] [3]. The robust penalty assigns additional covariance uncertainty to portfolio directions that are in the subspace orthogonal to the factor-model loading matrix, under the selected cross-sectional weighting metric.

The base covariance is assumed to have the factor structure

\[\Sigma = B F B^\top + D\]

where \(B\) is the loading matrix, \(F\) is the factor covariance matrix and \(D\) is the idiosyncratic covariance matrix.

Under this uncertainty set, the worst-case variance for a portfolio with weights \(w\) is

\[\sup_{\Sigma \in U} w^\top \Sigma\, w = w^\top \hat{\Sigma} w + \kappa \min_z \lVert C w - Q z \rVert_2^2.\]

Here, \(Q\) is an orthonormal basis of the weighted factor span \(\operatorname{col}(W^{1/2} B)\) and \(C = W^{-1/2}\).

The expression is the compact form of the quadratic penalty

\[\kappa C^\top (I - Q Q^\top) C.\]

This structured form avoids the lifted SDP formulation used for fully generic covariance uncertainty sets and avoids materializing the dense matrix [4] \(C^\top (I - Q Q^\top) C\).

If the factor model uses basket-neutral constraints, the loading matrix is first reduced to its effective full-rank basis before the orthogonal subspace is computed.

Parameters:
radiusfloat, default=1.0

Penalty radius \(\kappa\). Controls the magnitude of the orthogonal covariance penalty. Must be non-negative.

cs_weightingCSWeighting, default=CSWeighting.INVERSE_IDIO_VARIANCE

Cross-sectional weighting used to define the orthogonality metric.

Attributes:
uncertainty_set_CompactCovarianceUncertaintySet

Fitted solver-ready uncertainty set containing the radius, diagonal metric square root and basis.

Methods

fit(X[, y, return_distribution])

Fit the orthogonal covariance uncertainty set.

get_metadata_routing()

Get metadata routing of this object.

get_params([deep])

Get parameters for this estimator.

partial_fit(X[, y, return_distribution])

Update the orthogonal covariance uncertainty set.

set_fit_request(*[, return_distribution])

Configure whether metadata should be requested to be passed to the fit method.

set_params(**params)

Set the parameters of this estimator.

set_partial_fit_request(*[, return_distribution])

Configure whether metadata should be requested to be passed to the partial_fit method.

Notes

This estimator requires a factor model in the return distribution. When used inside MeanRisk, the return_distribution metadata is passed automatically by fit and partial_fit. Covariance uncertainty is applied when risk_measure=RiskMeasure.VARIANCE or when max_variance is set.

References

[1]

“Robustness properties of mean-variance portfolios”, Optimization: A Journal of Mathematical Programming and Operations Research, Schöttle & Werner (2009).

[2]

“Portfolio Optimization: Theory and Application”, Chapter 14, Daniel P. Palomar (2025)

[3]

“Robust Portfolio Selection Problems”, Mathematics of Operations Research, Goldfarb and Iyengar (2003).

[4]

“Robust Convex Optimization”, Mathematics of Operations Research, Ben-Tal and Nemirovski (1998).

fit(X, y=None, *, return_distribution=None, **fit_params)[source]#

Fit the orthogonal covariance uncertainty set.

Parameters:
Xarray-like of shape (n_observations, n_assets)

Price returns of the assets.

yarray-like of shape (n_observations, n_factors), optional

Price returns of factors. The default is None.

return_distributionReturnDistribution, optional

The fitted return distribution from the prior estimator. Passed internally by MeanRisk. Must contain a factor_model with loading_matrix and idio_covariance.

**fit_paramsdict

Additional parameters (unused).

Returns:
selfOrthogonalCovarianceUncertaintySet

Fitted estimator.

get_metadata_routing()#

Get metadata routing of this object.

Please check User Guide on how the routing mechanism works.

Returns:
routingMetadataRequest

A MetadataRequest encapsulating routing information.

get_params(deep=True)#

Get parameters for this estimator.

Parameters:
deepbool, default=True

If True, will return the parameters for this estimator and contained subobjects that are estimators.

Returns:
paramsdict

Parameter names mapped to their values.

partial_fit(X, y=None, *, return_distribution=None, **fit_params)[source]#

Update the orthogonal covariance uncertainty set.

Parameters:
Xarray-like of shape (n_observations, n_assets)

Price returns of the assets.

yarray-like of shape (n_observations, n_factors), optional

Price returns of factors. The default is None.

return_distributionReturnDistribution, optional

The fitted return distribution from the prior estimator. Passed internally by MeanRisk. Must contain a factor_model with loading_matrix and idio_covariance.

**fit_paramsdict

Additional parameters (unused).

Returns:
selfOrthogonalCovarianceUncertaintySet

Updated estimator.

set_fit_request(*, return_distribution='$UNCHANGED$')#

Configure whether metadata should be requested to be passed to the fit method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to fit if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to fit.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:
return_distributionstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for return_distribution parameter in fit.

Returns:
selfobject

The updated object.

set_params(**params)#

Set the parameters of this estimator.

The method works on simple estimators as well as on nested objects (such as Pipeline). The latter have parameters of the form <component>__<parameter> so that it’s possible to update each component of a nested object.

Parameters:
**paramsdict

Estimator parameters.

Returns:
selfestimator instance

Estimator instance.

set_partial_fit_request(*, return_distribution='$UNCHANGED$')#

Configure whether metadata should be requested to be passed to the partial_fit method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to partial_fit if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to partial_fit.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:
return_distributionstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for return_distribution parameter in partial_fit.

Returns:
selfobject

The updated object.