HKUDS/Vibe-Trading · error · ValueError

{design.shape[1]} regressors but only {design.shape[0]} asse

Error message

{design.shape[1]} regressors but only {design.shape[0]} assets; the fit would be exactly determined and meaningless

What it means

The Fama-MacBeth design matrix includes an intercept (the market factor) plus one column per exposure; if the number of regressors exceeds the number of assets, the OLS fit would be exactly determined (zero residual degrees of freedom) and the 'factor returns' would be meaningless interpolation, so it is rejected.

Source

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

            the inputs, if the design matrix has more columns than rows, or if
            the exposures are perfectly collinear.
    """
    common = returns.dropna().index.intersection(exposures.dropna(how="any").index)
    if len(common) < MIN_CROSS_SECTION:
        raise ValueError(
            f"cross-sectional regression needs at least {MIN_CROSS_SECTION} assets "
            f"with both a return and full exposures, got {len(common)}"
        )

    y = returns.loc[common].to_numpy(dtype=float)
    factor_names = list(exposures.columns)
    design = np.column_stack(
        [np.ones(len(common)), exposures.loc[common].to_numpy(dtype=float)]
    )
    names = [MARKET_FACTOR, *factor_names]

    if design.shape[1] > design.shape[0]:
        raise ValueError(
            f"{design.shape[1]} regressors but only {design.shape[0]} assets; "
            "the fit would be exactly determined and meaningless"
        )

    if market_caps is None:
        weights = np.ones(len(common))
    else:
        caps = pd.Series(market_caps, dtype=float).reindex(common)
        if caps.isna().any() or (caps <= 0).any():
            raise ValueError(
                "market_caps must be positive and defined for every asset in the "
                "regression"
            )
        weights = np.sqrt(caps.to_numpy(dtype=float))

    sqrt_w = np.sqrt(weights)
    design_w = design * sqrt_w[:, None]
    y_w = y * sqrt_w

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Reduce the number of factors (subset the exposure columns) or enlarge the universe so assets >= factors + 1.
  2. Check that exposures wasn't accidentally transposed (factors as rows).

Example fix

# before
fr = cross_sectional_factor_returns(returns, exposures)  # 20 cols, 12 assets
# after
keep = ["value", "momentum", "size"]
fr = cross_sectional_factor_returns(returns, exposures[keep])
Defensive patterns

Strategy: validation

Validate before calling

assert exposures.shape[1] + 1 <= returns.dropna().index.intersection(exposures.dropna(how='any').index).size

Prevention

When it happens

Trigger: More style factors than assets in the cross-section — e.g. 20 factor columns but only 12 stocks passing the completeness filter, common when a broad definition set meets a small pilot universe.

Common situations: Running the full style definition set on a narrow universe or a single sector, or after the complete-row filter in error 576 slashes the sample.

Related errors


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