HKUDS/Vibe-Trading · error · ValueError
steps_per_year must be >= 1, got {steps_per_year}
Error message
steps_per_year must be >= 1, got {steps_per_year} What it means
monte_carlo_gbm discretizes time as dt = 1/steps_per_year and needs steps_per_year >= 1 (e.g. 252 for daily, 12 for monthly, 1 for annual). Values below 1 would imply steps longer than a year via division by a fraction, breaking the intended convention, and 0 would divide by zero.
Source
Thrown at agent/src/quantlib/risk.py:565
Defaults to the 252-day trading year.
Returns:
Price matrix of shape ``(n_paths, n_steps + 1)``. Column 0 is exactly
``s0`` on every path, so ``paths[:, -1] / paths[:, 0] - 1`` is the total
return over the whole simulation.
Raises:
ValueError: If ``s0`` is not positive, ``sigma`` is negative, or any of
``n_steps`` / ``n_paths`` / ``steps_per_year`` is below 1.
"""
if s0 <= 0.0:
raise ValueError(f"s0 must be > 0, got {s0}")
if sigma < 0.0:
raise ValueError(f"sigma must be >= 0, got {sigma}")
if n_steps < 1 or n_paths < 1:
raise ValueError(f"n_steps and n_paths must be >= 1, got {n_steps} and {n_paths}")
if steps_per_year < 1:
raise ValueError(f"steps_per_year must be >= 1, got {steps_per_year}")
dt = 1.0 / steps_per_year
rng = np.random.default_rng(seed)
shocks = rng.standard_normal((n_paths, n_steps))
log_returns = (mu - 0.5 * sigma**2) * dt + sigma * np.sqrt(dt) * shocks
paths = np.empty((n_paths, n_steps + 1), dtype=float)
paths[:, 0] = s0
paths[:, 1:] = s0 * np.exp(np.cumsum(log_returns, axis=1))
return paths
def analyze_mc_results(paths: np.ndarray, confidence: float = 0.95) -> dict:
"""Summarise the terminal distribution of a simulated price matrix.
Args:
paths: Price matrix of shape ``(n_paths, n_steps + 1)`` as returned by
``monte_carlo_gbm``; column 0 is the starting price.
confidence: Confidence level for the VaR/CVaR of the terminal return.View on GitHub (pinned to 80ffdda44c)
Solutions
- Pass the frequency: 252 for daily, 52 weekly, 12 monthly, 1 annual
- If you have a step size dt, pass steps_per_year=1/dt (guarding dt > 0)
- Validate steps_per_year is an integer >= 1 in config
Example fix
// before paths = monte_carlo_gbm(s0=100, mu=0.05, sigma=0.2, n_steps=252, steps_per_year=1/252) // after paths = monte_carlo_gbm(s0=100, mu=0.05, sigma=0.2, n_steps=252, steps_per_year=252)
Defensive patterns
Strategy: validation
Validate before calling
steps_per_year = max(1, int(round(steps_per_year)))
Type guard
def is_valid_steps_per_year(x) -> bool:
return isinstance(x, (int, float)) and not isinstance(x, bool) and x >= 1 Try / catch
try:
paths = monte_carlo_gbm(..., steps_per_year=spy)
except ValueError as e:
if "steps_per_year" in str(e):
paths = monte_carlo_gbm(..., steps_per_year=int(round(1 / spy)) if 0 < spy < 1 else int(spy))
else:
raise Prevention
- Remember the convention: 252 = daily, 52 = weekly, 12 = monthly
- If you hold dt, pass steps_per_year=1/dt
- Document units next to config keys
When it happens
Trigger: monte_carlo_gbm(..., steps_per_year=0), or passing a fractional/intraday-miscomputed value like steps_per_year=1/252 (inverting the convention, i.e. passing step size instead of frequency).
Common situations: Confusing 'step size in years' with 'steps per year' — passing 1/252 instead of 252; deriving the value from an empty trading calendar.
Related errors
- s0 must be > 0, got {s0}
- sigma must be >= 0, got {sigma}
- n_steps and n_paths must be >= 1, got {n_steps} and {n_paths
- paths must be 2-D with >= 2 columns, got shape {matrix.shape
- paths column 0 (the starting price) must be strictly positiv
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/69c4619ffce6f796.
Report an issue: GitHub.