HKUDS/Vibe-Trading · error · ValueError

estimation window needs at least {MIN_ESTIMATION_OBSERVATION

Error message

estimation window needs at least {MIN_ESTIMATION_OBSERVATIONS} finite observations, got {n}

What it means

Raised by estimate_market_model when, after dropping non-finite observations, the estimation window contains fewer than MIN_ESTIMATION_OBSERVATIONS usable (asset, market) return pairs. The market model needs a minimum sample to produce meaningful alpha/beta estimates, so the library refuses rather than returning noisy parameters.

Source

Thrown at agent/src/quantlib/eventstudy.py:241

            model (beta would be undefined).
    """
    if model not in NORMAL_RETURN_MODELS:
        raise ValueError(
            f"model must be one of {NORMAL_RETURN_MODELS}, got {model!r}"
        )

    asset = np.asarray(asset_returns, dtype=float).ravel()
    market = np.asarray(market_returns, dtype=float).ravel()
    if asset.size != market.size:
        raise ValueError(
            f"asset and market must be the same length, got {asset.size} and {market.size}"
        )

    keep = np.isfinite(asset) & np.isfinite(market)
    asset, market = asset[keep], market[keep]
    n = asset.size
    if n < MIN_ESTIMATION_OBSERVATIONS:
        raise ValueError(
            f"estimation window needs at least {MIN_ESTIMATION_OBSERVATIONS} "
            f"finite observations, got {n}"
        )

    market_mean = float(market.mean())
    market_sum_squares = float(np.sum((market - market_mean) ** 2))

    if model == "market":
        if market_sum_squares <= 0.0:
            raise ValueError(
                "market returns are constant over the estimation window, so beta "
                "is not identified; use model='mean_adjusted'"
            )
        beta = float(np.sum((market - market_mean) * (asset - asset.mean())) / market_sum_squares)
        alpha = float(asset.mean() - beta * market_mean)
        residuals = asset - (alpha + beta * market)
        dof = n - 2
    elif model == "market_adjusted":

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Inspect the estimation window slice for NaN/inf: asset[start:end].dropna() and count the rows.
  2. Increase estimation_window or shift the event date so at least MIN_ESTIMATION_OBSERVATIONS finite overlapping observations exist.
  3. Align market_returns to returns.index (fill or reindex) before calling event_study.

Example fix

# before
car = event_study(returns, market, events, estimation_window=20)
# after
car = event_study(returns.dropna(), market.reindex(returns.index).ffill(), events, estimation_window=120)
Defensive patterns

Strategy: validation

Validate before calling

finite = np.isfinite(asset[est_slice]) & np.isfinite(market[est_slice])
assert finite.sum() >= MIN_ESTIMATION_OBSERVATIONS, finite.sum()

Prevention

When it happens

Trigger: Calling event_study (or estimate_market_model directly) with an estimation_window shorter than the minimum, NaN/inf values in either return series over the estimation window, or market_returns missing labels so the intersection shrinks below the threshold.

Common situations: Short back-history for a newly listed asset, holidays/missing dates in the market index alignment, early sample periods where the rolling window runs off the start of the data, or a data pipeline leaking NaNs.

Related errors


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