ZhuLinsen/daily_stock_analysis · error · ValueError

eval_window_days must be a positive integer

Error message

eval_window_days must be a positive integer

What it means

BacktestService.run_backtest validates eval_window_days before running an evaluation: it must be a non-boolean int greater than 0. When the argument is None the service falls back to config.backtest_eval_window_days (default 10), so the error fires either on a bad explicit argument or a corrupt config value. It is raised as a plain ValueError, which the FastAPI backtest endpoint translates to HTTP 400 invalid_params.

Source

Thrown at src/services/backtest_service.py:71

        analysis_date_to: Optional[date] = None,
        limit: int = 200,
    ) -> Dict[str, Any]:
        config = get_config()

        if analysis_date_from and analysis_date_to and analysis_date_from > analysis_date_to:
            raise ValueError("analysis_date_from cannot be after analysis_date_to")

        query_code = self._normalize_code(code)
        diagnostic_code = self._normalize_code_for_display(code)

        if eval_window_days is None:
            eval_window_days = getattr(config, "backtest_eval_window_days", 10)
        if (
            isinstance(eval_window_days, bool)
            or not isinstance(eval_window_days, int)
            or eval_window_days <= 0
        ):
            raise ValueError("eval_window_days must be a positive integer")
        if min_age_days is None:
            min_age_days = getattr(config, "backtest_min_age_days", 14)

        engine_version = getattr(config, "backtest_engine_version", "v1")
        neutral_band_pct = float(getattr(config, "backtest_neutral_band_pct", 2.0))

        eval_config = EvaluationConfig(
            eval_window_days=int(eval_window_days),
            neutral_band_pct=neutral_band_pct,
            engine_version=str(engine_version),
        )

        limit_int = int(limit)
        candidates = self._get_run_candidates(
            code=query_code,
            min_age_days=int(min_age_days),
            limit=limit_int,
            eval_window_days=int(eval_window_days),

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Pass eval_window_days as a positive int (e.g. 10) or omit it so the config default (10) applies.
  2. Check the effective config: python -c "from src.config.config import get_config; print(get_config().backtest_eval_window_days)" and fix .env / BACKTEST_EVAL_WINDOW_DAYS.
  3. If the value arrives from a client as a string, coerce with int() and validate > 0 before calling the service (the API schema should already enforce ge=1, le=120).

Example fix

# before
service.run_backtest(code="600519", eval_window_days="20")

# after
service.run_backtest(code="600519", eval_window_days=20)
Defensive patterns

Strategy: validation

Validate before calling

def valid_eval_window(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v > 0

if eval_window_days is not None and not valid_eval_window(eval_window_days):
    raise HTTPException(400, "eval_window_days must be a positive integer")
service.run_backtest(code=code, eval_window_days=eval_window_days)

Type guard

def isPositiveInt(v: object) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v > 0

Try / catch

try:
    service.run_backtest(code=code, eval_window_days=eval_window_days)
except ValueError as exc:
    if "eval_window_days" in str(exc):
        return JSONResponse(status_code=400, content={"error": "invalid_params", "message": str(exc)})
    raise

Prevention

When it happens

Trigger: Calling POST /api/v1/backtest/run (or BacktestService.run_backtest) with eval_window_days=0, a negative int, a string like "10", a float like 7.5, or True/False; or setting backtest_eval_window_days=0/-1/"7d" in .env/config so the fallback value itself is invalid.

Common situations: Typos in .env (BACKTEST_EVAL_WINDOW_DAYS=10.5 or empty string parsed as 0), passing a bool because the value came from a JSON query string ("true" coerced), or a frontend sending the field as a string from a form input.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/6db0a5480e768dae. Report an issue: GitHub.