{"record":{"id":"7e3e9b8ea0e85dbd","repo":"ZhuLinsen/daily_stock_analysis","slug":"futu-code","errorCode":null,"errorMessage":"Futu 非零持仓返回了无效证券代码: {code}","messagePattern":"Futu 非零持仓返回了无效证券代码: (.+?)","errorType":"exception","errorClass":"FutuPortfolioError","httpStatus":null,"severity":"error","filePath":"src/brokers/futu/portfolio.py","lineNumber":295,"sourceCode":"                try:\n                    if isinstance(raw_quantity, bool):\n                        raise TypeError(\"boolean quantity\")\n                    quantity = float(raw_quantity)\n                except (TypeError, ValueError) as exc:\n                    suffix = f\": {code}\" if code else \"\"\n                    raise FutuPortfolioError(f\"Futu 持仓数量无效{suffix}\") from exc\n                if not math.isfinite(quantity):\n                    suffix = f\": {code}\" if code else \"\"\n                    raise FutuPortfolioError(f\"Futu 持仓数量无效{suffix}\")\n                if quantity == 0:\n                    continue\n                if not isinstance(raw_code, str):\n                    raise FutuPortfolioError(\"Futu 非零持仓返回了无效证券代码\")\n                if not code:\n                    raise FutuPortfolioError(\"Futu 非零持仓返回了空证券代码\")\n                market, separator, symbol = code.partition(\".\")\n                if not separator or not market or not symbol:\n                    raise FutuPortfolioError(\n                        f\"Futu 非零持仓返回了无效证券代码: {code}\"\n                    )\n                if code in seen_codes:\n                    continue\n                seen_codes.add(code)\n                codes.append(code)\n        except FutuPortfolioError:\n            raise\n        except Exception as exc:  # noqa: BLE001 - translate SDK/network errors for CLI callers\n            raise FutuPortfolioError(f\"查询 Futu 真实持仓失败: {exc}\") from exc\n        finally:\n            _safe_close(context)\n\n    if skipped_short_count:\n        logger.info(\"已跳过 %d 个 Futu SHORT 空头持仓\", skipped_short_count)\n    if skipped_unknown_side_count:\n        logger.warning(\n            \"已跳过 %d 个持仓方向不是 LONG 的 Futu 持仓\",","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/brokers/futu/portfolio.py#L277-L313","documentation":"Raised when a non-zero position's code is a non-empty string but does not contain the expected '<MARKET>.<SYMBOL>' shape (e.g. '00700' with no dot, '.00700', or 'HK.'). The loader partitions on '.' and requires market, separator, and symbol all present so it can later group codes by market prefix for get_stock_basicinfo classification. A malformed code means the security cannot be routed to a market query.","triggerScenarios":"position_list returns codes in a bare format like '00700' or 'AAPL' without the 'HK.'/'US.'/'SH.' market prefix, or codes that are just a market prefix 'HK.'. Also triggered by whitespace-only symbols that survived the earlier checks (partition succeeds but symbol part is empty).","commonSituations":"SDK schema change dropping the market prefix; custom/mock data fed into the loader; positions in markets whose code format differs from the expected dotted convention.","solutions":["Log/inspect the actual code value from the exception message (it is included verbatim) to see which shape arrived.","Ensure futu-api version matches FutuOpenD so codes keep the MARKET.SYMBOL format.","If codes legitimately lack the prefix, map them to the account's market before calling this loader rather than patching the guard."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"def is_dotted_futu_code(code: str) -> bool:\n    market, sep, symbol = code.partition(\".\")\n    return bool(sep and market and symbol)","typeGuard":"def is_futu_code(value: object) -> bool:\n    if not isinstance(value, str):\n        return False\n    m, s, sym = value.partition(\".\")\n    return bool(s and m and sym)","tryCatchPattern":"try:\n    codes = load_futu_stock_codes()\nexcept FutuPortfolioError as exc:\n    logger.error(\"Futu code contract violated: %s\", exc)\n    raise","preventionTips":["Keep futu-api version aligned with FutuOpenD releases","Never hand-craft position codes without the MARKET.SYMBOL shape","Log raw SDK rows when contract errors first appear to capture schema drift"],"tags":["futu","broker","data-contract","formatting"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}