HKUDS/Vibe-Trading · error · ValueError

portfolio_weights cannot be empty

Error message

portfolio_weights cannot be empty

What it means

factor_risk_decomposition refuses an empty portfolio_weights input because risk of nothing is undefined (and downstream linear algebra would fail anyway).

Source

Thrown at agent/src/quantlib/factormodel.py:634

    Args:
        portfolio_weights: Asset weights in the portfolio.
        exposures: Asset factor exposures (rows = assets, columns = factors).
        factor_cov: Covariance matrix of factor returns (K x K).
        specific_variances: Asset-specific (idiosyncratic) return variances.
            Defaults to zero if omitted.

    Returns:
        :class:`FactorRiskDecomposition` containing total/factor/specific
        variances, volatilities, marginal contributions to risk (MCR), and
        percentage contributions to risk (PCR) per factor and per asset.

    Raises:
        ValueError: If weights or matrices are empty, contain non-finite values,
            or share no common assets or factors.
    """
    w_series = pd.Series(portfolio_weights, dtype=float)
    if w_series.empty:
        raise ValueError("portfolio_weights cannot be empty")
    if not np.isfinite(w_series.values).all():
        raise ValueError("portfolio_weights contains non-finite values")

    if not isinstance(exposures, pd.DataFrame) or exposures.empty:
        raise ValueError("exposures must be a non-empty DataFrame")
    if not np.isfinite(exposures.values).all():
        raise ValueError("exposures contains non-finite values")

    if not isinstance(factor_cov, pd.DataFrame) or factor_cov.empty:
        raise ValueError("factor_cov must be a non-empty DataFrame")
    if not np.isfinite(factor_cov.values).all():
        raise ValueError("factor_cov contains non-finite values")

    # Align assets
    assets = w_series.index.intersection(exposures.index)
    if assets.empty:
        raise ValueError(
            f"No matching assets between weights ({sorted(w_series.index)}) and exposures ({sorted(exposures.index)})"

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Check len(portfolio_weights) before calling
  2. Log the portfolio ID/weights source when it comes up empty
  3. Return a zero-risk result upstream instead of calling the API

Example fix

# before
risk = factor_risk_decomposition(w, X, F)
# after
risk = factor_risk_decomposition(w, X, F) if len(w) else None
Defensive patterns

Strategy: validation

Validate before calling

assert len(portfolio_weights) > 0

Prevention

When it happens

Trigger: Passing portfolio_weights={}, an empty list, or an empty pd.Series.

Common situations: Empty book passed to a nightly risk job; positions filtered out by a universe screen before the call.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/7680647240229792. Report an issue: GitHub.