HKUDS/Vibe-Trading · error · ValueError

No matching assets between weights ({sorted(w_series.index)}

Error message

No matching assets between weights ({sorted(w_series.index)}) and exposures ({sorted(exposures.index)})

What it means

Weights are aligned to exposures by asset (row) index; if w_series.index and exposures.index share no ticker, there is nothing to risk-decompose and the message prints both sets to expose the mismatch.

Source

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

    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)})"
        )

    unmatched_weight = float(w_series.drop(index=assets, errors="ignore").abs().sum())
    w = w_series.loc[assets]
    X = exposures.loc[assets]

    # Align factors
    factors = X.columns.intersection(factor_cov.index).intersection(factor_cov.columns)
    if factors.empty:
        raise ValueError(
            f"No matching factors between exposures ({sorted(X.columns)}) and factor_cov ({sorted(factor_cov.index)})"
        )

    X = X[factors]
    F = factor_cov.loc[factors, factors]
    F_mat = F.to_numpy(dtype=float)
    if not np.allclose(F_mat, F_mat.T, atol=1e-8):

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Compare the two sorted index lists shown in the message
  2. Normalize identifiers (strip suffixes, map via security master) before the call
  3. Reindex exposures onto the weights' tickers after mapping

Example fix

# before
risk = factor_risk_decomposition(w, X, F)
# after
X = X.rename(index=sec_master_map)  # align identifiers
risk = factor_risk_decomposition(w, X, F)
Defensive patterns

Strategy: validation

Validate before calling

assert w_series.index.intersection(exposures.index).size > 0

Try / catch

try:
    risk = factor_risk_decomposition(w, X, F)
except ValueError as e:
    if 'No matching assets' in str(e):
        log_identifiers(w.index, X.index)
    raise

Prevention

When it happens

Trigger: Weights keyed 'AAPL US Equity' vs exposures 'AAPL'; CUSIP vs ticker identifiers; weights from a different universe than the exposure file.

Common situations: Security-master identifier mismatch between the portfolio system and the risk model vendor file.

Related errors


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