HKUDS/Vibe-Trading · error · ValueError

paths column 0 (the starting price) must be strictly positiv

Error message

paths column 0 (the starting price) must be strictly positive

What it means

analyze_mc_results uses column 0 as the starting price to compute returns (terminal/start - 1), so every entry in that column must be strictly positive. A zero or negative starting price makes the return ratio undefined and would corrupt every statistic derived from it.

Source

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

                returns over the simulation, so a bad outcome is negative.
            var, cvar (float): Positive loss magnitudes, computed with the same
                order-statistic convention as ``historical_var`` /
                ``historical_cvar``, so ``cvar >= var``.
            prob_loss (float): Fraction of paths ending below their start.
            worst_5pct_return, best_5pct_return (float): Signed 5th and 95th
                percentiles of the terminal return (linear interpolation).

    Raises:
        ValueError: If ``paths`` is not 2-D with at least two columns, holds a
            non-positive starting price, or ``confidence`` is outside (0, 1).
    """
    _validate_confidence(confidence)
    matrix = np.asarray(paths, dtype=float)
    if matrix.ndim != 2 or matrix.shape[1] < 2:
        raise ValueError(f"paths must be 2-D with >= 2 columns, got shape {matrix.shape}")
    start = matrix[:, 0]
    if (start <= 0.0).any():
        raise ValueError("paths column 0 (the starting price) must be strictly positive")

    returns = matrix[:, -1] / start - 1.0
    return {
        "mean_return": float(np.mean(returns)),
        "median_return": float(np.median(returns)),
        "std_return": float(np.std(returns, ddof=1)) if returns.size > 1 else 0.0,
        "var": historical_var(returns, confidence),
        "cvar": historical_cvar(returns, confidence),
        "prob_loss": float(np.mean(returns < 0.0)),
        "worst_5pct_return": float(np.percentile(returns, 5.0)),
        "best_5pct_return": float(np.percentile(returns, 95.0)),
    }


def fit_gpd_tail(
    returns: pd.Series | np.ndarray | Sequence[float],
    threshold_pct: float = 5.0,
) -> dict:

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Ensure column 0 holds the positive starting prices (monte_carlo_gbm already does this)
  2. If you dropped s0, prepend it: np.hstack([np.full((n,1), s0), returns_matrix])
  3. Convert log-price matrices with np.exp before analysis

Example fix

// before
stats = analyze_mc_results(returns_matrix)  # col 0 is returns, can be <= 0
// after
stats = analyze_mc_results(np.hstack([np.full((returns_matrix.shape[0], 1), s0), returns_matrix]))
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
m = np.asarray(paths, dtype=float)
assert (m[:, 0] > 0).all(), "column 0 must hold positive starting prices"

Type guard

import numpy as np

def has_positive_start_col(x) -> bool:
    m = np.asarray(x, dtype=float)
    return m.ndim == 2 and m.shape[1] >= 2 and bool((m[:, 0] > 0).all())

Try / catch

try:
    stats = analyze_mc_results(paths)
except ValueError as e:
    if "starting price" in str(e):
        stats = analyze_mc_results(np.hstack([np.full((paths.shape[0], 1), s0), paths]))
    else:
        raise

Prevention

When it happens

Trigger: Passing a matrix whose first column contains 0 or negative values — e.g. a PnL matrix instead of price paths, paths built with s0=0, or a matrix where the s0 column was dropped/shifted (returns stacked in col 0).

Common situations: Concatenating simulation output incorrectly (np.hstack of returns without the s0 column); passing log-prices or PnL; sign errors in path construction.

Related errors


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