{"record":{"id":"37e5ff17423e3f8b","repo":"HKUDS/Vibe-Trading","slug":"s0-must-be-0-got-s0","errorCode":null,"errorMessage":"s0 must be > 0, got {s0}","messagePattern":"s0 must be > 0, got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/risk.py","lineNumber":559,"sourceCode":"        n_paths: Number of paths, at least 1. Use 10,000 or more before reading\n            anything off the tail.\n        seed: Seed for ``numpy.random.default_rng``. Keyword-only. Pass an int\n            for a reproducible run; None draws fresh OS entropy and the result\n            is then NOT reproducible.\n        steps_per_year: Steps per year, i.e. ``dt = 1 / steps_per_year``.\n            Defaults to the 252-day trading year.\n\n    Returns:\n        Price matrix of shape ``(n_paths, n_steps + 1)``. Column 0 is exactly\n        ``s0`` on every path, so ``paths[:, -1] / paths[:, 0] - 1`` is the total\n        return over the whole simulation.\n\n    Raises:\n        ValueError: If ``s0`` is not positive, ``sigma`` is negative, or any of\n            ``n_steps`` / ``n_paths`` / ``steps_per_year`` is below 1.\n    \"\"\"\n    if s0 <= 0.0:\n        raise ValueError(f\"s0 must be > 0, got {s0}\")\n    if sigma < 0.0:\n        raise ValueError(f\"sigma must be >= 0, got {sigma}\")\n    if n_steps < 1 or n_paths < 1:\n        raise ValueError(f\"n_steps and n_paths must be >= 1, got {n_steps} and {n_paths}\")\n    if steps_per_year < 1:\n        raise ValueError(f\"steps_per_year must be >= 1, got {steps_per_year}\")\n\n    dt = 1.0 / steps_per_year\n    rng = np.random.default_rng(seed)\n    shocks = rng.standard_normal((n_paths, n_steps))\n    log_returns = (mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * shocks\n    paths = np.empty((n_paths, n_steps + 1), dtype=float)\n    paths[:, 0] = s0\n    paths[:, 1:] = s0 * np.exp(np.cumsum(log_returns, axis=1))\n    return paths\n\n\ndef analyze_mc_results(paths: np.ndarray, confidence: float = 0.95) -> dict:","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/risk.py#L541-L577","documentation":"monte_carlo_gbm simulates geometric Brownian motion, whose log-return formulation requires a strictly positive initial price s0. s0 <= 0 (including 0) makes the log-normal process mathematically undefined, so it is rejected before any sampling.","triggerScenarios":"monte_carlo_gbm(s0=0, mu=0.05, sigma=0.2, ...), a negative s0 from a sign error, or s0 read from a missing config key defaulting to 0.","commonSituations":"Unset config values defaulting to 0; misparsed instrument prices; tests that pass placeholder values before wiring real data.","solutions":["Pass the actual positive starting price (e.g. today's close)","Default missing config to a sensible positive value and validate","Check for sign inversions if s0 comes from PnL-style data"],"exampleFix":"// before\npaths = monte_carlo_gbm(s0=cfg.get(\"s0\", 0), ...)\n// after\ns0 = cfg.get(\"s0\")\npaths = monte_carlo_gbm(s0=s0 if s0 and s0 > 0 else spot_close, ...)","handlingStrategy":"validation","validationCode":"assert s0 is not None and s0 > 0, f\"s0 must be positive, got {s0}!r\"","typeGuard":"def is_valid_s0(x) -> bool:\n    return isinstance(x, (int, float)) and not isinstance(x, bool) and x > 0","tryCatchPattern":"try:\n    paths = monte_carlo_gbm(s0, ...)\nexcept ValueError as e:\n    if \"s0 must be > 0\" in str(e):\n        raise ValueError(f\"bad spot price from feed: {s0}\") from e\n    raise","preventionTips":["Validate market data feed values before simulation","Default config s0 to the latest close, never 0","Fail fast on non-positive instrument prices at ingest"],"tags":["quantlib","risk","monte-carlo","gbm","validation","valueerror"],"backgroundTag":"invalid-domain-value","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}