HKUDS/Vibe-Trading · error · ValueError

returns contains no finite observation

Error message

returns contains no finite observation

What it means

Raised by _clean_returns when the returns series passed to a risk statistic (historical_var, parametric_var, historical_cvar, fit_gpd_tail) contains zero finite values — i.e. it is empty, or every element is NaN/inf. The library requires at least one finite observation to compute any tail statistic, so it fails fast rather than returning NaN.

Source

Thrown at agent/src/quantlib/risk.py:95

    """Coerce a return series to a finite 1-D float array.

    Args:
        returns: Return observations as a pandas Series, numpy array or any
            sequence of floats. NaN and infinite values are dropped.

    Returns:
        A 1-D float64 array of the finite observations, in input order.

    Raises:
        ValueError: If the input is not 1-D or holds no finite observation.
    """
    values = np.asarray(returns, dtype=float)
    if values.ndim > 1:
        raise ValueError(f"returns must be 1-D, got shape {values.shape}")
    values = values.ravel()
    finite = values[np.isfinite(values)]
    if finite.size == 0:
        raise ValueError("returns contains no finite observation")
    return finite


def _validate_confidence(confidence: float) -> None:
    """Check that a confidence level is a strict probability.

    Args:
        confidence: Confidence level, e.g. 0.95.

    Raises:
        ValueError: If ``confidence`` is not strictly between 0 and 1.
    """
    if not 0.0 < confidence < 1.0:
        raise ValueError(f"confidence must be in (0, 1), got {confidence}")


def _validate_horizon(horizon: int) -> None:
    """Check that a holding period is a positive whole number of periods.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Check the input series length and np.isfinite(values).sum() before calling the risk function
  2. Drop NaN/inf rows: returns = pd.Series(returns).replace([np.inf,-np.inf], np.nan).dropna()
  3. Log the series head/dtype to find the upstream pipeline stage that emptied it
  4. If an empty input is legitimate in your flow, guard with a length check and skip or return NaN explicitly

Example fix

// before
var = historical_var(returns, confidence=0.95)  # returns is all NaN
// after
returns = pd.Series(returns).replace([np.inf, -np.inf], np.nan).dropna()
var = historical_var(returns, confidence=0.95) if len(returns) else float("nan")
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def finite_returns_ok(r):
    v = np.asarray(r, dtype=float).ravel()
    return np.isfinite(v).sum() > 0
# call only when finite_returns_ok(returns)

Type guard

def has_finite_returns(returns) -> bool:
    import numpy as np
    v = np.asarray(returns, dtype=float).ravel()
    return bool(np.isfinite(v).any())

Try / catch

try:
    var = historical_var(returns, 0.95)
except ValueError as e:
    if "no finite observation" in str(e):
        logger.warning("empty return series; skipping VaR")
        var = float("nan")
    else:
        raise

Prevention

When it happens

Trigger: Calling historical_var([], 0.95), parametric_var([np.nan]*10), or fit_gpd_tail with a series of all-NaN (e.g. a price series diff'd after leading NaNs, or an empty dataframe column).

Common situations: Loading a CSV with wrong column name (all NaN), a pandas pipeline that produced an empty slice (e.g. df[df.date > max_date]), or forward-filled price data turned into returns where the NaN row was not dropped.

Related errors


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