ZhuLinsen/daily_stock_analysis · error · ValueError

非法股票代码格式: {code}

Error message

非法股票代码格式: {code}

What it means

BacktestService._normalize_code resolves the stock code through resolve_daily_stock_identity; if that helper cannot recognize the code's format (A-share, HK, US conventions), it returns None and the service raises ValueError with the original input. This guards every backtest entry point (run, results, summaries, export) so only codes the daily-data layer can fetch are accepted.

Source

Thrown at src/services/backtest_service.py:431

        for analysis in candidates:
            analysis_date = self._resolve_analysis_date(analysis)
            if analysis_date is None:
                continue
            if analysis_date_from is not None and analysis_date < analysis_date_from:
                continue
            if analysis_date_to is not None and analysis_date > analysis_date_to:
                continue
            filtered.append(analysis)
        return filtered

    @staticmethod
    def _normalize_code(code: Optional[str]) -> Optional[str]:
        if not code:
            return None

        identity = resolve_daily_stock_identity(str(code).strip())
        if identity is None:
            raise ValueError(f"非法股票代码格式: {code}")
        return identity.normalized_code

    @staticmethod
    def _normalize_summary_code(code: Optional[str]) -> Optional[str]:
        if not code:
            return None
        raw_code = str(code).strip()
        normalized = normalize_stock_code(raw_code)
        backtest_normalized = normalize_backtest_code(raw_code)
        if raw_code.upper().startswith("SS") and backtest_normalized and backtest_normalized != normalized:
            normalized = backtest_normalized
        return canonical_stock_code(normalized or raw_code)

    @staticmethod
    def _normalize_code_for_display(code: Optional[str]) -> Optional[str]:
        return BacktestService._normalize_code(code)

    @staticmethod

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Use the canonical code format the resolver expects: A-share "600519"/"000001", HK "hk00700", US "AAPL".
  2. Verify the code resolves first: from src.utils.stock_code import resolve_daily_stock_identity; resolve_daily_stock_identity("hk00700").
  3. Pass code=None to query all stocks instead of an invalid sentinel like "all" or "*".

Example fix

# before
service.get_recent_evaluations(code="700.HK")

# after
service.get_recent_evaluations(code="hk00700")
Defensive patterns

Strategy: validation

Validate before calling

from src.utils.stock_code import resolve_daily_stock_identity

def isResolvableCode(code: str) -> bool:
    return resolve_daily_stock_identity(code.strip()) is not None

if code and not isResolvableCode(code):
    return JSONResponse(status_code=400, content={"error": "invalid_code", "message": f"unrecognized code: {code}"})

Type guard

from typing import Optional
from src.utils.stock_code import resolve_daily_stock_identity

def validBacktestCode(code: Optional[str]) -> bool:
    if not code:
        return True  # None means 'all stocks'
    return resolve_daily_stock_identity(str(code).strip()) is not None

Try / catch

try:
    service.run_backtest(code=code)
except ValueError as exc:
    if "非法股票代码格式" in str(exc):
        return JSONResponse(status_code=400, content={"error": "invalid_code", "message": str(exc)})
    raise

Prevention

When it happens

Trigger: Calling any BacktestService method or /api/v1/backtest/* endpoint with code="12345" (not 6 digits), "60051X", "hk0700 " style variants that resolve_daily_stock_identity rejects, random strings, or a code from another market convention the identity resolver does not support.

Common situations: Users pasting a stock name instead of a code, typos, mixing exchanges (e.g. "00700" without the hk prefix when the resolver requires it for HK), or test fixtures using placeholder codes like "TEST".

Related errors


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