ZhuLinsen/daily_stock_analysis · error · ValueError

stock_code is required

Error message

stock_code is required

What it means

ValueError from DecisionSignalService._normalize_stock_code (src/services/decision_signal_service.py:1118): after stripping and canonicalization (canonical_stock_code / _normalize_hk_stock_code per market), the resulting code is empty, so no stock identity can be established. The market branch decides the canonical form; all branches collapse to '' only when the raw input has no usable content (or normalizers reject it).

Source

Thrown at src/services/decision_signal_service.py:1118

        return list(dict.fromkeys([normalized, hk_normalized]))

    @classmethod
    def normalize_stock_code_for_signal(cls, value: Any, *, market: Optional[str] = None) -> str:
        """Normalize a stock code for DecisionSignal identity matching."""

        return cls._normalize_stock_code(value, market=market)

    @classmethod
    def _normalize_stock_code(cls, value: Any, *, market: Optional[str] = None) -> str:
        raw = str(value or "").strip()
        if market == "us":
            code = canonical_stock_code(raw)
        elif market == "hk":
            code = cls._normalize_hk_stock_code(raw)
        else:
            code = canonical_stock_code(normalize_stock_code(raw))
        if not code:
            raise ValueError("stock_code is required")
        return code

    @staticmethod
    def _normalize_hk_stock_code(value: str) -> str:
        normalized = canonical_stock_code(normalize_stock_code(value))
        digits = ""
        if normalized.startswith("HK"):
            digits = normalized[2:]
        elif normalized.isdigit():
            digits = normalized
        if digits.isdigit() and 1 <= len(digits) <= 5:
            return f"HK{digits.zfill(5)}"
        return normalized

    @staticmethod
    def _normalize_market(value: Any) -> str:
        market = str(value or "").strip().lower()
        if market not in VALID_MARKETS:

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Make stock_code mandatory in the client payload schema and fail before calling the service.
  2. Map your ticker field to stock_code explicitly when constructing the payload.
  3. For imports, drop or quarantine rows with blank stock_code rather than sending them.
  4. Verify the code format matches the declared market (cn: 6-digit, hk: 1–5 digit payload, us: ticker).

Example fix

# before
service.create_signal({"market": "cn", "action": "buy", "stock_code": getattr(row, "ticker", None)})  # attribute is 'code' → blank → ValueError

# after
service.create_signal({"market": "cn", "action": "buy", "stock_code": row.code})
Defensive patterns

Strategy: validation

Validate before calling

code = str(payload.get('stock_code') or '').strip()
if not code:
    raise ValueError('stock_code missing: fix payload construction before calling the service')

Type guard

def has_stock_code(payload: dict) -> bool:
    return bool(str(payload.get('stock_code') or '').strip())

Prevention

When it happens

Trigger: create/update signal payloads where stock_code is missing, None, whitespace, or a value that normalizes to empty — e.g. '--', 'N/A', punctuation-only strings. Also HK codes that normalize to a non-digit prefix (e.g. 'HKFOO') still return non-empty, so the empty case is essentially blank/absent input; wrong-market pairing can surface elsewhere.

Common situations: Payload built dynamically and the code key is undefined; client sends stock symbol under a different key (symbol/ticker) leaving stock_code blank; CSV/import rows with empty cells; defensive code passing getattr(obj, 'code', None) on objects without that attribute.

Related errors


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