{"record":{"id":"396e8145b2d67fde","repo":"HKUDS/Vibe-Trading","slug":"spot-min-must-be-non-negative","errorCode":null,"errorMessage":"spot_min must be non-negative","messagePattern":"spot_min must be non-negative","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/options_payoff_tool.py","lineNumber":311,"sourceCode":"    except (TypeError, ValueError, OverflowError) as exc:\n        raise ValueError(\"spot_points must be an integer\") from exc\n    if not math.isfinite(numeric) or not numeric.is_integer():\n        raise ValueError(\"spot_points must be an integer\")\n    points = int(numeric)\n    if not _MIN_SPOT_POINTS <= points <= _MAX_SPOT_POINTS:\n        raise ValueError(f\"spot_points must be between {_MIN_SPOT_POINTS} and {_MAX_SPOT_POINTS}\")\n    return points\n\n\ndef _spot_bounds(kwargs: dict[str, Any], legs: list[OptionLeg], entry_spot: float) -> tuple[float, float]:\n    \"\"\"Resolve explicit chart bounds or safe defaults covering every strike.\"\"\"\n    reference = [entry_spot, *(leg.strike for leg in legs)]\n    default_min = max(min(reference) * 0.5, 0.0)\n    default_max = max(reference) * 1.5\n    spot_min = _optional_float(kwargs, \"spot_min\", default_min)\n    spot_max = _optional_float(kwargs, \"spot_max\", default_max)\n    if spot_min < 0:\n        raise ValueError(\"spot_min must be non-negative\")\n    if spot_max <= spot_min:\n        raise ValueError(\"spot_max must be greater than spot_min\")\n    return spot_min, spot_max\n\n\ndef _scenario_ivs(raw: Any, entry_iv: float) -> np.ndarray:\n    \"\"\"Resolve bounded explicit IV scenarios or the skill's five defaults.\"\"\"\n    if raw is None:\n        values = [\n            entry_iv * 0.5,\n            entry_iv * 0.75,\n            entry_iv,\n            entry_iv * 1.25,\n            entry_iv * 1.5,\n        ]\n    else:\n        if not isinstance(raw, list) or not raw:\n            raise ValueError(\"scenario_iv_values must be a non-empty array\")","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/options_payoff_tool.py#L293-L329","documentation":"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.","triggerScenarios":"spot_min=-20, or a mis-signed value like a percentage -0.1 passed as an absolute price.","commonSituations":"Relative/threshold inputs mistakenly used as absolute prices; sign errors from delta-based computations; testing with dummy negatives.","solutions":["Pass an absolute non-negative price for spot_min","Convert relative offsets: spot_min=max(entry_spot-offset, 0.0)","Omit spot_min to use the computed default (half the lowest reference)"],"exampleFix":"// before\nexecute({..., \"spot_min\": -10})\n// after\nexecute({..., \"spot_min\": 0.0})","handlingStrategy":"validation","validationCode":"if kwargs.get(\"spot_min\") is not None:\n    kwargs[\"spot_min\"] = max(float(kwargs[\"spot_min\"]), 0.0)","typeGuard":"def spot_min_valid(v) -> bool:\n    return v is None or (isinstance(v,(int,float)) and v >= 0)","tryCatchPattern":"try:\n    execute(kwargs)\nexcept ValueError as e:\n    if \"non-negative\" in str(e):\n        kwargs[\"spot_min\"] = 0.0; execute(kwargs)","preventionTips":["Clamp lower bounds to 0 in UIs","Convert relative offsets to absolute prices before sending","Prefer defaults for the min bound"],"tags":["validation","options","chart-bounds"],"backgroundTag":"value-out-of-range","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}