Skip to content

Optimize

Portfolio construction is exposed through a thin sklearn-compatible layer: optimisers implement fit(X) / predict(X) -> Portfolio / score(X), which means they slot into sklearn.pipeline.Pipeline and GridSearchCV the same way any estimator does. When the [pf] extra is installed, skfolio's full family (MeanRisk, HRP, HERC, and friends) is reachable through Fundcloud with RiskMeasure.VARIANCE, CVAR, EVAR, MDD and related measures. Without the extra, EqualWeighted, InverseVolatility, and MVO remain available as pure-Python fallbacks — same interface, same estimator checks. See the interop guide for end-to-end pipelines.

fundcloud.optimize

Portfolio optimisation.

Always available: the pure-Python fallback optimisers (:class:EqualWeighted, :class:InverseVolatility, :class:MVO) from :mod:fundcloud.optimize.fallback_mvo.

Behind the [pf] extra: the skfolio adapters (:class:MeanRisk, :class:RiskBudgeting, :class:HierarchicalRiskParity, …) are imported lazily so the core install stays cheap.

When both sets name the same class (e.g. EqualWeighted) the skfolio version wins when the extra is installed; otherwise the fallback is returned. This keeps user code identical whether or not skfolio is present; it just loses the richer constraint language when skfolio is missing.

EqualWeighted module-attribute

EqualWeighted = _make_adapter(
    "EqualWeighted", EqualWeighted
)

InverseVolatility module-attribute

InverseVolatility = _make_adapter(
    "InverseVolatility", InverseVolatility
)

RiskMeasure module-attribute

RiskMeasure: type[Enum] = RiskMeasure

MVO

MVO(risk_free: float = 0.0, l2: float = 0.0)

Bases: BaseFallbackOptimizer

Mean-Variance Optimiser — max-Sharpe under long-only, fully-invested.

Parameters:

Name Type Description Default
risk_free float

Per-period risk-free rate (same units as returns). Defaults to 0.

0.0
l2 float

Optional L2 regularisation on the weight vector (helps when covariance is ill-conditioned).

0.0
Source code in python/fundcloud/optimize/fallback_mvo.py
def __init__(self, risk_free: float = 0.0, l2: float = 0.0) -> None:
    self.risk_free = float(risk_free)
    self.l2 = float(l2)

BaseFallbackOptimizer

Bases: BaseEstimator

Common machinery: sklearn fit / predict / score contract.

score

score(X: DataFrame, y: object | None = None) -> float

Higher is better — defaults to annualised Sharpe on predict(X).

Source code in python/fundcloud/optimize/fallback_mvo.py
def score(self, X: pd.DataFrame, y: object | None = None) -> float:
    """Higher is better — defaults to annualised Sharpe on ``predict(X)``."""
    return float(self.predict(X).sharpe())