HKUDS/Vibe-Trading · error · ValueError

spot_min must be non-negative

Error message

spot_min must be non-negative

What it means

Thrown by _spot_bounds when an explicitly supplied (or defaulted) spot_min is negative. Spot prices cannot go below zero, so the payoff chart's lower bound must be non-negative. Defaults are clamped via max(..., 0.0), so this fires only for caller-supplied negative values.

Source

Thrown at agent/src/tools/options_payoff_tool.py:311

    except (TypeError, ValueError, OverflowError) as exc:
        raise ValueError("spot_points must be an integer") from exc
    if not math.isfinite(numeric) or not numeric.is_integer():
        raise ValueError("spot_points must be an integer")
    points = int(numeric)
    if not _MIN_SPOT_POINTS <= points <= _MAX_SPOT_POINTS:
        raise ValueError(f"spot_points must be between {_MIN_SPOT_POINTS} and {_MAX_SPOT_POINTS}")
    return points


def _spot_bounds(kwargs: dict[str, Any], legs: list[OptionLeg], entry_spot: float) -> tuple[float, float]:
    """Resolve explicit chart bounds or safe defaults covering every strike."""
    reference = [entry_spot, *(leg.strike for leg in legs)]
    default_min = max(min(reference) * 0.5, 0.0)
    default_max = max(reference) * 1.5
    spot_min = _optional_float(kwargs, "spot_min", default_min)
    spot_max = _optional_float(kwargs, "spot_max", default_max)
    if spot_min < 0:
        raise ValueError("spot_min must be non-negative")
    if spot_max <= spot_min:
        raise ValueError("spot_max must be greater than spot_min")
    return spot_min, spot_max


def _scenario_ivs(raw: Any, entry_iv: float) -> np.ndarray:
    """Resolve bounded explicit IV scenarios or the skill's five defaults."""
    if raw is None:
        values = [
            entry_iv * 0.5,
            entry_iv * 0.75,
            entry_iv,
            entry_iv * 1.25,
            entry_iv * 1.5,
        ]
    else:
        if not isinstance(raw, list) or not raw:
            raise ValueError("scenario_iv_values must be a non-empty array")

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass an absolute non-negative price for spot_min
  2. Convert relative offsets: spot_min=max(entry_spot-offset, 0.0)
  3. Omit spot_min to use the computed default (half the lowest reference)

Example fix

// before
execute({..., "spot_min": -10})
// after
execute({..., "spot_min": 0.0})
Defensive patterns

Strategy: validation

Validate before calling

if kwargs.get("spot_min") is not None:
    kwargs["spot_min"] = max(float(kwargs["spot_min"]), 0.0)

Type guard

def spot_min_valid(v) -> bool:
    return v is None or (isinstance(v,(int,float)) and v >= 0)

Try / catch

try:
    execute(kwargs)
except ValueError as e:
    if "non-negative" in str(e):
        kwargs["spot_min"] = 0.0; execute(kwargs)

Prevention

When it happens

Trigger: spot_min=-20, or a mis-signed value like a percentage -0.1 passed as an absolute price.

Common situations: Relative/threshold inputs mistakenly used as absolute prices; sign errors from delta-based computations; testing with dummy negatives.

Related errors


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